@massu/core 0.1.1 → 0.4.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/commands/_shared-preamble.md +76 -0
- package/commands/massu-audit-deps.md +211 -0
- package/commands/massu-changelog.md +174 -0
- package/commands/massu-cleanup.md +315 -0
- package/commands/massu-commit.md +481 -0
- package/commands/massu-create-plan.md +752 -0
- package/commands/massu-dead-code.md +131 -0
- package/commands/massu-debug.md +484 -0
- package/commands/massu-deploy.md +91 -0
- package/commands/massu-deps.md +374 -0
- package/commands/massu-doc-gen.md +279 -0
- package/commands/massu-docs.md +364 -0
- package/commands/massu-estimate.md +313 -0
- package/commands/massu-golden-path.md +973 -0
- package/commands/massu-guide.md +167 -0
- package/commands/massu-hotfix.md +480 -0
- package/commands/massu-loop-playwright.md +837 -0
- package/commands/massu-loop.md +775 -0
- package/commands/massu-new-feature.md +511 -0
- package/commands/massu-parity.md +214 -0
- package/commands/massu-plan.md +456 -0
- package/commands/massu-push-light.md +207 -0
- package/commands/massu-push.md +434 -0
- package/commands/massu-refactor.md +410 -0
- package/commands/massu-release.md +363 -0
- package/commands/massu-review.md +238 -0
- package/commands/massu-simplify.md +281 -0
- package/commands/massu-status.md +278 -0
- package/commands/massu-tdd.md +201 -0
- package/commands/massu-test.md +516 -0
- package/commands/massu-verify-playwright.md +281 -0
- package/commands/massu-verify.md +667 -0
- package/dist/cli.js +7772 -3140
- package/dist/hooks/cost-tracker.js +103 -40
- package/dist/hooks/post-edit-context.js +74 -8
- package/dist/hooks/post-tool-use.js +268 -106
- package/dist/hooks/pre-compact.js +167 -43
- package/dist/hooks/pre-delete-check.js +159 -42
- package/dist/hooks/quality-event.js +103 -40
- package/dist/hooks/security-gate.js +29 -0
- package/dist/hooks/session-end.js +143 -84
- package/dist/hooks/session-start.js +186 -49
- package/dist/hooks/user-prompt.js +189 -43
- package/package.json +10 -15
- package/src/adr-generator.ts +9 -2
- package/src/analytics.ts +9 -3
- package/src/audit-trail.ts +10 -3
- package/src/backfill-sessions.ts +5 -4
- package/src/cli.ts +6 -0
- package/src/cloud-sync.ts +14 -18
- package/src/commands/doctor.ts +193 -6
- package/src/commands/init.ts +230 -5
- package/src/commands/install-commands.ts +137 -0
- package/src/config.ts +68 -2
- package/src/cost-tracker.ts +11 -6
- package/src/db.ts +115 -2
- package/src/dependency-scorer.ts +9 -2
- package/src/docs-tools.ts +21 -16
- package/src/hooks/post-edit-context.ts +4 -4
- package/src/hooks/post-tool-use.ts +130 -0
- package/src/hooks/pre-compact.ts +23 -1
- package/src/hooks/pre-delete-check.ts +92 -4
- package/src/hooks/security-gate.ts +32 -0
- package/src/hooks/session-end.ts +3 -3
- package/src/hooks/session-start.ts +99 -6
- package/src/hooks/user-prompt.ts +46 -1
- package/src/import-resolver.ts +2 -1
- package/src/knowledge-db.ts +169 -0
- package/src/knowledge-indexer.ts +704 -0
- package/src/knowledge-tools.ts +1413 -0
- package/src/license.ts +482 -0
- package/src/memory-db.ts +1364 -23
- package/src/memory-tools.ts +14 -15
- package/src/observability-tools.ts +13 -2
- package/src/observation-extractor.ts +11 -4
- package/src/page-deps.ts +3 -2
- package/src/prompt-analyzer.ts +9 -2
- package/src/python/coupling-detector.ts +124 -0
- package/src/python/domain-enforcer.ts +83 -0
- package/src/python/impact-analyzer.ts +95 -0
- package/src/python/import-parser.ts +244 -0
- package/src/python/import-resolver.ts +135 -0
- package/src/python/migration-indexer.ts +115 -0
- package/src/python/migration-parser.ts +332 -0
- package/src/python/model-indexer.ts +70 -0
- package/src/python/model-parser.ts +279 -0
- package/src/python/route-indexer.ts +58 -0
- package/src/python/route-parser.ts +317 -0
- package/src/python-tools.ts +629 -0
- package/src/regression-detector.ts +9 -3
- package/src/security-scorer.ts +9 -2
- package/src/sentinel-db.ts +45 -89
- package/src/sentinel-tools.ts +8 -11
- package/src/server.ts +29 -7
- package/src/session-archiver.ts +4 -5
- package/src/team-knowledge.ts +9 -2
- package/src/tools.ts +1032 -44
- package/src/validate-features-runner.ts +0 -1
- package/src/validation-engine.ts +9 -2
- package/README.md +0 -40
- package/dist/server.js +0 -7008
- package/src/__tests__/adr-generator.test.ts +0 -260
- package/src/__tests__/analytics.test.ts +0 -282
- package/src/__tests__/audit-trail.test.ts +0 -382
- package/src/__tests__/backfill-sessions.test.ts +0 -690
- package/src/__tests__/cli.test.ts +0 -290
- package/src/__tests__/cloud-sync.test.ts +0 -261
- package/src/__tests__/config-sections.test.ts +0 -359
- package/src/__tests__/config.test.ts +0 -732
- package/src/__tests__/cost-tracker.test.ts +0 -348
- package/src/__tests__/db.test.ts +0 -177
- package/src/__tests__/dependency-scorer.test.ts +0 -325
- package/src/__tests__/docs-integration.test.ts +0 -178
- package/src/__tests__/docs-tools.test.ts +0 -199
- package/src/__tests__/domains.test.ts +0 -236
- package/src/__tests__/hooks.test.ts +0 -221
- package/src/__tests__/import-resolver.test.ts +0 -95
- package/src/__tests__/integration/path-traversal.test.ts +0 -134
- package/src/__tests__/integration/pricing-consistency.test.ts +0 -88
- package/src/__tests__/integration/tool-registration.test.ts +0 -146
- package/src/__tests__/memory-db.test.ts +0 -404
- package/src/__tests__/memory-enhancements.test.ts +0 -316
- package/src/__tests__/memory-tools.test.ts +0 -199
- package/src/__tests__/middleware-tree.test.ts +0 -177
- package/src/__tests__/observability-tools.test.ts +0 -595
- package/src/__tests__/observability.test.ts +0 -437
- package/src/__tests__/observation-extractor.test.ts +0 -167
- package/src/__tests__/page-deps.test.ts +0 -60
- package/src/__tests__/prompt-analyzer.test.ts +0 -298
- package/src/__tests__/regression-detector.test.ts +0 -295
- package/src/__tests__/rules.test.ts +0 -87
- package/src/__tests__/schema-mapper.test.ts +0 -29
- package/src/__tests__/security-scorer.test.ts +0 -238
- package/src/__tests__/security-utils.test.ts +0 -175
- package/src/__tests__/sentinel-db.test.ts +0 -491
- package/src/__tests__/sentinel-scanner.test.ts +0 -750
- package/src/__tests__/sentinel-tools.test.ts +0 -324
- package/src/__tests__/sentinel-types.test.ts +0 -750
- package/src/__tests__/server.test.ts +0 -452
- package/src/__tests__/session-archiver.test.ts +0 -524
- package/src/__tests__/session-state-generator.test.ts +0 -900
- package/src/__tests__/team-knowledge.test.ts +0 -327
- package/src/__tests__/tools.test.ts +0 -340
- package/src/__tests__/transcript-parser.test.ts +0 -195
- package/src/__tests__/trpc-index.test.ts +0 -25
- package/src/__tests__/validate-features-runner.test.ts +0 -517
- package/src/__tests__/validation-engine.test.ts +0 -300
- package/src/core-tools.ts +0 -685
- package/src/memory-queries.ts +0 -804
- package/src/memory-schema.ts +0 -546
- package/src/tool-helpers.ts +0 -41
|
@@ -3,12 +3,13 @@ import{createRequire as __cr}from"module";const require=__cr(import.meta.url);
|
|
|
3
3
|
|
|
4
4
|
// src/memory-db.ts
|
|
5
5
|
import Database from "better-sqlite3";
|
|
6
|
-
import { dirname as dirname2 } from "path";
|
|
6
|
+
import { dirname as dirname2, basename } from "path";
|
|
7
7
|
import { existsSync as existsSync2, mkdirSync } from "fs";
|
|
8
8
|
|
|
9
9
|
// src/config.ts
|
|
10
10
|
import { resolve, dirname } from "path";
|
|
11
11
|
import { existsSync, readFileSync } from "fs";
|
|
12
|
+
import { homedir } from "os";
|
|
12
13
|
import { parse as parseYaml } from "yaml";
|
|
13
14
|
import { z } from "zod";
|
|
14
15
|
var DomainConfigSchema = z.object({
|
|
@@ -140,6 +141,49 @@ var CloudConfigSchema = z.object({
|
|
|
140
141
|
audit: z.boolean().default(true)
|
|
141
142
|
}).default({ memory: true, analytics: true, audit: true })
|
|
142
143
|
}).optional();
|
|
144
|
+
var ConventionsConfigSchema = z.object({
|
|
145
|
+
claudeDirName: z.string().default(".claude").refine(
|
|
146
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
147
|
+
{ message: 'claudeDirName must not contain ".." or start with "/"' }
|
|
148
|
+
),
|
|
149
|
+
sessionStatePath: z.string().default(".claude/session-state/CURRENT.md").refine(
|
|
150
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
151
|
+
{ message: 'sessionStatePath must not contain ".." or start with "/"' }
|
|
152
|
+
),
|
|
153
|
+
sessionArchivePath: z.string().default(".claude/session-state/archive").refine(
|
|
154
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
155
|
+
{ message: 'sessionArchivePath must not contain ".." or start with "/"' }
|
|
156
|
+
),
|
|
157
|
+
knowledgeCategories: z.array(z.string()).default([
|
|
158
|
+
"patterns",
|
|
159
|
+
"commands",
|
|
160
|
+
"incidents",
|
|
161
|
+
"reference",
|
|
162
|
+
"protocols",
|
|
163
|
+
"checklists",
|
|
164
|
+
"playbooks",
|
|
165
|
+
"critical",
|
|
166
|
+
"scripts",
|
|
167
|
+
"status",
|
|
168
|
+
"templates",
|
|
169
|
+
"loop-state",
|
|
170
|
+
"session-state",
|
|
171
|
+
"agents"
|
|
172
|
+
]),
|
|
173
|
+
knowledgeSourceFiles: z.array(z.string()).default(["CLAUDE.md", "MEMORY.md", "corrections.md"]),
|
|
174
|
+
excludePatterns: z.array(z.string()).default(["/ARCHIVE/", "/SESSION-HISTORY/"])
|
|
175
|
+
}).optional();
|
|
176
|
+
var PythonDomainConfigSchema = z.object({
|
|
177
|
+
name: z.string(),
|
|
178
|
+
packages: z.array(z.string()),
|
|
179
|
+
allowed_imports_from: z.array(z.string()).default([])
|
|
180
|
+
});
|
|
181
|
+
var PythonConfigSchema = z.object({
|
|
182
|
+
root: z.string(),
|
|
183
|
+
alembic_dir: z.string().optional(),
|
|
184
|
+
domains: z.array(PythonDomainConfigSchema).default([]),
|
|
185
|
+
exclude_dirs: z.array(z.string()).default(["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"])
|
|
186
|
+
}).optional();
|
|
143
187
|
var PathsConfigSchema = z.object({
|
|
144
188
|
source: z.string().default("src"),
|
|
145
189
|
aliases: z.record(z.string(), z.string()).default({ "@": "src" }),
|
|
@@ -174,7 +218,9 @@ var RawConfigSchema = z.object({
|
|
|
174
218
|
security: SecurityConfigSchema,
|
|
175
219
|
team: TeamConfigSchema,
|
|
176
220
|
regression: RegressionConfigSchema,
|
|
177
|
-
cloud: CloudConfigSchema
|
|
221
|
+
cloud: CloudConfigSchema,
|
|
222
|
+
conventions: ConventionsConfigSchema,
|
|
223
|
+
python: PythonConfigSchema
|
|
178
224
|
}).passthrough();
|
|
179
225
|
var _config = null;
|
|
180
226
|
var _projectRoot = null;
|
|
@@ -238,13 +284,24 @@ function getConfig() {
|
|
|
238
284
|
security: parsed.security,
|
|
239
285
|
team: parsed.team,
|
|
240
286
|
regression: parsed.regression,
|
|
241
|
-
cloud: parsed.cloud
|
|
287
|
+
cloud: parsed.cloud,
|
|
288
|
+
conventions: parsed.conventions,
|
|
289
|
+
python: parsed.python
|
|
242
290
|
};
|
|
291
|
+
if (!_config.cloud?.apiKey && process.env.MASSU_API_KEY) {
|
|
292
|
+
_config.cloud = {
|
|
293
|
+
enabled: true,
|
|
294
|
+
sync: { memory: true, analytics: true, audit: true },
|
|
295
|
+
..._config.cloud,
|
|
296
|
+
apiKey: process.env.MASSU_API_KEY
|
|
297
|
+
};
|
|
298
|
+
}
|
|
243
299
|
return _config;
|
|
244
300
|
}
|
|
245
301
|
function getResolvedPaths() {
|
|
246
302
|
const config = getConfig();
|
|
247
303
|
const root = getProjectRoot();
|
|
304
|
+
const claudeDirName = config.conventions?.claudeDirName ?? ".claude";
|
|
248
305
|
return {
|
|
249
306
|
codegraphDbPath: resolve(root, ".codegraph/codegraph.db"),
|
|
250
307
|
dataDbPath: resolve(root, ".massu/data.db"),
|
|
@@ -260,22 +317,43 @@ function getResolvedPaths() {
|
|
|
260
317
|
),
|
|
261
318
|
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
262
319
|
indexFiles: ["index.ts", "index.tsx", "index.js", "index.jsx"],
|
|
263
|
-
patternsDir: resolve(root, "
|
|
264
|
-
claudeMdPath: resolve(root, "
|
|
320
|
+
patternsDir: resolve(root, claudeDirName, "patterns"),
|
|
321
|
+
claudeMdPath: resolve(root, claudeDirName, "CLAUDE.md"),
|
|
265
322
|
docsMapPath: resolve(root, ".massu/docs-map.json"),
|
|
266
323
|
helpSitePath: resolve(root, "../" + config.project.name + "-help"),
|
|
267
|
-
memoryDbPath: resolve(root, ".massu/memory.db")
|
|
324
|
+
memoryDbPath: resolve(root, ".massu/memory.db"),
|
|
325
|
+
knowledgeDbPath: resolve(root, ".massu/knowledge.db"),
|
|
326
|
+
plansDir: resolve(root, "docs/plans"),
|
|
327
|
+
docsDir: resolve(root, "docs"),
|
|
328
|
+
claudeDir: resolve(root, claudeDirName),
|
|
329
|
+
memoryDir: resolve(homedir(), claudeDirName, "projects", root.replace(/\//g, "-"), "memory"),
|
|
330
|
+
sessionStatePath: resolve(root, config.conventions?.sessionStatePath ?? `${claudeDirName}/session-state/CURRENT.md`),
|
|
331
|
+
sessionArchivePath: resolve(root, config.conventions?.sessionArchivePath ?? `${claudeDirName}/session-state/archive`),
|
|
332
|
+
mcpJsonPath: resolve(root, ".mcp.json"),
|
|
333
|
+
settingsLocalPath: resolve(root, claudeDirName, "settings.local.json")
|
|
268
334
|
};
|
|
269
335
|
}
|
|
270
336
|
|
|
271
|
-
// src/memory-
|
|
337
|
+
// src/memory-db.ts
|
|
338
|
+
function getMemoryDb() {
|
|
339
|
+
const dbPath = getResolvedPaths().memoryDbPath;
|
|
340
|
+
const dir = dirname2(dbPath);
|
|
341
|
+
if (!existsSync2(dir)) {
|
|
342
|
+
mkdirSync(dir, { recursive: true });
|
|
343
|
+
}
|
|
344
|
+
const db = new Database(dbPath);
|
|
345
|
+
db.pragma("journal_mode = WAL");
|
|
346
|
+
db.pragma("foreign_keys = ON");
|
|
347
|
+
initMemorySchema(db);
|
|
348
|
+
return db;
|
|
349
|
+
}
|
|
272
350
|
function initMemorySchema(db) {
|
|
273
351
|
db.exec(`
|
|
274
352
|
-- Sessions table (linked to Claude Code session IDs)
|
|
275
353
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
276
354
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
277
355
|
session_id TEXT UNIQUE NOT NULL,
|
|
278
|
-
project TEXT NOT NULL DEFAULT '
|
|
356
|
+
project TEXT NOT NULL DEFAULT 'my-project',
|
|
279
357
|
git_branch TEXT,
|
|
280
358
|
started_at TEXT NOT NULL,
|
|
281
359
|
started_at_epoch INTEGER NOT NULL,
|
|
@@ -330,9 +408,7 @@ function initMemorySchema(db) {
|
|
|
330
408
|
content_rowid='id'
|
|
331
409
|
);
|
|
332
410
|
`);
|
|
333
|
-
} catch (
|
|
334
|
-
process.stderr.write(`FTS5 setup warning: ${e instanceof Error ? e.message : String(e)}
|
|
335
|
-
`);
|
|
411
|
+
} catch (_e) {
|
|
336
412
|
}
|
|
337
413
|
db.exec(`
|
|
338
414
|
CREATE TRIGGER IF NOT EXISTS observations_ai AFTER INSERT ON observations BEGIN
|
|
@@ -392,9 +468,7 @@ function initMemorySchema(db) {
|
|
|
392
468
|
content_rowid='id'
|
|
393
469
|
);
|
|
394
470
|
`);
|
|
395
|
-
} catch (
|
|
396
|
-
process.stderr.write(`FTS5 setup warning: ${e instanceof Error ? e.message : String(e)}
|
|
397
|
-
`);
|
|
471
|
+
} catch (_e) {
|
|
398
472
|
}
|
|
399
473
|
db.exec(`
|
|
400
474
|
CREATE TRIGGER IF NOT EXISTS prompts_ai AFTER INSERT ON user_prompts BEGIN
|
|
@@ -464,9 +538,7 @@ function initMemorySchema(db) {
|
|
|
464
538
|
content_rowid=id
|
|
465
539
|
);
|
|
466
540
|
`);
|
|
467
|
-
} catch (
|
|
468
|
-
process.stderr.write(`FTS5 setup warning: ${e instanceof Error ? e.message : String(e)}
|
|
469
|
-
`);
|
|
541
|
+
} catch (_e) {
|
|
470
542
|
}
|
|
471
543
|
db.exec(`
|
|
472
544
|
CREATE TRIGGER IF NOT EXISTS ct_fts_insert AFTER INSERT ON conversation_turns BEGIN
|
|
@@ -490,7 +562,7 @@ function initMemorySchema(db) {
|
|
|
490
562
|
CREATE TABLE IF NOT EXISTS session_quality_scores (
|
|
491
563
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
492
564
|
session_id TEXT NOT NULL UNIQUE,
|
|
493
|
-
project TEXT NOT NULL DEFAULT '
|
|
565
|
+
project TEXT NOT NULL DEFAULT 'my-project',
|
|
494
566
|
score INTEGER NOT NULL DEFAULT 100,
|
|
495
567
|
security_score INTEGER NOT NULL DEFAULT 100,
|
|
496
568
|
architecture_score INTEGER NOT NULL DEFAULT 100,
|
|
@@ -513,7 +585,7 @@ function initMemorySchema(db) {
|
|
|
513
585
|
CREATE TABLE IF NOT EXISTS session_costs (
|
|
514
586
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
515
587
|
session_id TEXT NOT NULL UNIQUE,
|
|
516
|
-
project TEXT NOT NULL DEFAULT '
|
|
588
|
+
project TEXT NOT NULL DEFAULT 'my-project',
|
|
517
589
|
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
518
590
|
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
519
591
|
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
@@ -740,24 +812,15 @@ function initMemorySchema(db) {
|
|
|
740
812
|
);
|
|
741
813
|
CREATE INDEX IF NOT EXISTS idx_pending_sync_created ON pending_sync(created_at ASC);
|
|
742
814
|
`);
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
}
|
|
753
|
-
const db = new Database(dbPath);
|
|
754
|
-
db.pragma("journal_mode = WAL");
|
|
755
|
-
db.pragma("foreign_keys = ON");
|
|
756
|
-
if (!initializedPaths.has(dbPath)) {
|
|
757
|
-
initMemorySchema(db);
|
|
758
|
-
initializedPaths.add(dbPath);
|
|
759
|
-
}
|
|
760
|
-
return db;
|
|
815
|
+
db.exec(`
|
|
816
|
+
CREATE TABLE IF NOT EXISTS license_cache (
|
|
817
|
+
api_key_hash TEXT PRIMARY KEY,
|
|
818
|
+
tier TEXT NOT NULL,
|
|
819
|
+
valid_until TEXT NOT NULL,
|
|
820
|
+
last_validated TEXT NOT NULL,
|
|
821
|
+
features TEXT DEFAULT '[]'
|
|
822
|
+
);
|
|
823
|
+
`);
|
|
761
824
|
}
|
|
762
825
|
|
|
763
826
|
// src/hooks/cost-tracker.ts
|
|
@@ -787,14 +850,14 @@ async function main() {
|
|
|
787
850
|
process.exit(0);
|
|
788
851
|
}
|
|
789
852
|
function readStdin() {
|
|
790
|
-
return new Promise((
|
|
853
|
+
return new Promise((resolve3) => {
|
|
791
854
|
let data = "";
|
|
792
855
|
process.stdin.setEncoding("utf-8");
|
|
793
856
|
process.stdin.on("data", (chunk) => {
|
|
794
857
|
data += chunk;
|
|
795
858
|
});
|
|
796
|
-
process.stdin.on("end", () =>
|
|
797
|
-
setTimeout(() =>
|
|
859
|
+
process.stdin.on("end", () => resolve3(data));
|
|
860
|
+
setTimeout(() => resolve3(data), 3e3);
|
|
798
861
|
});
|
|
799
862
|
}
|
|
800
863
|
main();
|
|
@@ -7,6 +7,7 @@ import Database from "better-sqlite3";
|
|
|
7
7
|
// src/config.ts
|
|
8
8
|
import { resolve, dirname } from "path";
|
|
9
9
|
import { existsSync, readFileSync } from "fs";
|
|
10
|
+
import { homedir } from "os";
|
|
10
11
|
import { parse as parseYaml } from "yaml";
|
|
11
12
|
import { z } from "zod";
|
|
12
13
|
var DomainConfigSchema = z.object({
|
|
@@ -138,6 +139,49 @@ var CloudConfigSchema = z.object({
|
|
|
138
139
|
audit: z.boolean().default(true)
|
|
139
140
|
}).default({ memory: true, analytics: true, audit: true })
|
|
140
141
|
}).optional();
|
|
142
|
+
var ConventionsConfigSchema = z.object({
|
|
143
|
+
claudeDirName: z.string().default(".claude").refine(
|
|
144
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
145
|
+
{ message: 'claudeDirName must not contain ".." or start with "/"' }
|
|
146
|
+
),
|
|
147
|
+
sessionStatePath: z.string().default(".claude/session-state/CURRENT.md").refine(
|
|
148
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
149
|
+
{ message: 'sessionStatePath must not contain ".." or start with "/"' }
|
|
150
|
+
),
|
|
151
|
+
sessionArchivePath: z.string().default(".claude/session-state/archive").refine(
|
|
152
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
153
|
+
{ message: 'sessionArchivePath must not contain ".." or start with "/"' }
|
|
154
|
+
),
|
|
155
|
+
knowledgeCategories: z.array(z.string()).default([
|
|
156
|
+
"patterns",
|
|
157
|
+
"commands",
|
|
158
|
+
"incidents",
|
|
159
|
+
"reference",
|
|
160
|
+
"protocols",
|
|
161
|
+
"checklists",
|
|
162
|
+
"playbooks",
|
|
163
|
+
"critical",
|
|
164
|
+
"scripts",
|
|
165
|
+
"status",
|
|
166
|
+
"templates",
|
|
167
|
+
"loop-state",
|
|
168
|
+
"session-state",
|
|
169
|
+
"agents"
|
|
170
|
+
]),
|
|
171
|
+
knowledgeSourceFiles: z.array(z.string()).default(["CLAUDE.md", "MEMORY.md", "corrections.md"]),
|
|
172
|
+
excludePatterns: z.array(z.string()).default(["/ARCHIVE/", "/SESSION-HISTORY/"])
|
|
173
|
+
}).optional();
|
|
174
|
+
var PythonDomainConfigSchema = z.object({
|
|
175
|
+
name: z.string(),
|
|
176
|
+
packages: z.array(z.string()),
|
|
177
|
+
allowed_imports_from: z.array(z.string()).default([])
|
|
178
|
+
});
|
|
179
|
+
var PythonConfigSchema = z.object({
|
|
180
|
+
root: z.string(),
|
|
181
|
+
alembic_dir: z.string().optional(),
|
|
182
|
+
domains: z.array(PythonDomainConfigSchema).default([]),
|
|
183
|
+
exclude_dirs: z.array(z.string()).default(["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"])
|
|
184
|
+
}).optional();
|
|
141
185
|
var PathsConfigSchema = z.object({
|
|
142
186
|
source: z.string().default("src"),
|
|
143
187
|
aliases: z.record(z.string(), z.string()).default({ "@": "src" }),
|
|
@@ -172,7 +216,9 @@ var RawConfigSchema = z.object({
|
|
|
172
216
|
security: SecurityConfigSchema,
|
|
173
217
|
team: TeamConfigSchema,
|
|
174
218
|
regression: RegressionConfigSchema,
|
|
175
|
-
cloud: CloudConfigSchema
|
|
219
|
+
cloud: CloudConfigSchema,
|
|
220
|
+
conventions: ConventionsConfigSchema,
|
|
221
|
+
python: PythonConfigSchema
|
|
176
222
|
}).passthrough();
|
|
177
223
|
var _config = null;
|
|
178
224
|
var _projectRoot = null;
|
|
@@ -236,13 +282,24 @@ function getConfig() {
|
|
|
236
282
|
security: parsed.security,
|
|
237
283
|
team: parsed.team,
|
|
238
284
|
regression: parsed.regression,
|
|
239
|
-
cloud: parsed.cloud
|
|
285
|
+
cloud: parsed.cloud,
|
|
286
|
+
conventions: parsed.conventions,
|
|
287
|
+
python: parsed.python
|
|
240
288
|
};
|
|
289
|
+
if (!_config.cloud?.apiKey && process.env.MASSU_API_KEY) {
|
|
290
|
+
_config.cloud = {
|
|
291
|
+
enabled: true,
|
|
292
|
+
sync: { memory: true, analytics: true, audit: true },
|
|
293
|
+
..._config.cloud,
|
|
294
|
+
apiKey: process.env.MASSU_API_KEY
|
|
295
|
+
};
|
|
296
|
+
}
|
|
241
297
|
return _config;
|
|
242
298
|
}
|
|
243
299
|
function getResolvedPaths() {
|
|
244
300
|
const config = getConfig();
|
|
245
301
|
const root = getProjectRoot();
|
|
302
|
+
const claudeDirName = config.conventions?.claudeDirName ?? ".claude";
|
|
246
303
|
return {
|
|
247
304
|
codegraphDbPath: resolve(root, ".codegraph/codegraph.db"),
|
|
248
305
|
dataDbPath: resolve(root, ".massu/data.db"),
|
|
@@ -258,11 +315,20 @@ function getResolvedPaths() {
|
|
|
258
315
|
),
|
|
259
316
|
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
260
317
|
indexFiles: ["index.ts", "index.tsx", "index.js", "index.jsx"],
|
|
261
|
-
patternsDir: resolve(root, "
|
|
262
|
-
claudeMdPath: resolve(root, "
|
|
318
|
+
patternsDir: resolve(root, claudeDirName, "patterns"),
|
|
319
|
+
claudeMdPath: resolve(root, claudeDirName, "CLAUDE.md"),
|
|
263
320
|
docsMapPath: resolve(root, ".massu/docs-map.json"),
|
|
264
321
|
helpSitePath: resolve(root, "../" + config.project.name + "-help"),
|
|
265
|
-
memoryDbPath: resolve(root, ".massu/memory.db")
|
|
322
|
+
memoryDbPath: resolve(root, ".massu/memory.db"),
|
|
323
|
+
knowledgeDbPath: resolve(root, ".massu/knowledge.db"),
|
|
324
|
+
plansDir: resolve(root, "docs/plans"),
|
|
325
|
+
docsDir: resolve(root, "docs"),
|
|
326
|
+
claudeDir: resolve(root, claudeDirName),
|
|
327
|
+
memoryDir: resolve(homedir(), claudeDirName, "projects", root.replace(/\//g, "-"), "memory"),
|
|
328
|
+
sessionStatePath: resolve(root, config.conventions?.sessionStatePath ?? `${claudeDirName}/session-state/CURRENT.md`),
|
|
329
|
+
sessionArchivePath: resolve(root, config.conventions?.sessionArchivePath ?? `${claudeDirName}/session-state/archive`),
|
|
330
|
+
mcpJsonPath: resolve(root, ".mcp.json"),
|
|
331
|
+
settingsLocalPath: resolve(root, claudeDirName, "settings.local.json")
|
|
266
332
|
};
|
|
267
333
|
}
|
|
268
334
|
|
|
@@ -302,7 +368,7 @@ async function main() {
|
|
|
302
368
|
}
|
|
303
369
|
const root = getProjectRoot();
|
|
304
370
|
const rel = filePath.startsWith(root + "/") ? filePath.slice(root.length + 1) : filePath;
|
|
305
|
-
if (!rel.startsWith("src/")) {
|
|
371
|
+
if (!rel.startsWith("src/") && !rel.endsWith(".py")) {
|
|
306
372
|
process.exit(0);
|
|
307
373
|
return;
|
|
308
374
|
}
|
|
@@ -319,7 +385,7 @@ async function main() {
|
|
|
319
385
|
const dataDb = new Database(getResolvedPaths().dataDbPath, { readonly: true });
|
|
320
386
|
try {
|
|
321
387
|
if (isInMiddlewareTree(dataDb, rel)) {
|
|
322
|
-
warnings.push("[CRITICAL]
|
|
388
|
+
warnings.push("[CRITICAL] This file is in the middleware import tree. No Node.js deps allowed.");
|
|
323
389
|
}
|
|
324
390
|
} finally {
|
|
325
391
|
dataDb.close();
|
|
@@ -327,7 +393,7 @@ async function main() {
|
|
|
327
393
|
} catch (_e) {
|
|
328
394
|
}
|
|
329
395
|
if (warnings.length > 0) {
|
|
330
|
-
console.log(`[
|
|
396
|
+
console.log(`[Massu] ${warnings.join(" | ")}`);
|
|
331
397
|
}
|
|
332
398
|
} catch (_e) {
|
|
333
399
|
}
|