@massu/core 2.5.1 → 2.5.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.
@@ -1167,6 +1167,13 @@ var init_config = __esm({
1167
1167
  });
1168
1168
  LanguageFrameworkEntrySchema = z2.object({
1169
1169
  framework: z2.string().optional(),
1170
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1171
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1172
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1173
+ // derives the index builders' candidate set from it, so it is typed here rather than
1174
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1175
+ // from silently contributing `undefined` to a path predicate.
1176
+ source_dirs: z2.array(z2.string()).optional(),
1170
1177
  test_framework: z2.string().optional(),
1171
1178
  test: z2.string().optional(),
1172
1179
  runtime: z2.string().optional(),
@@ -4016,6 +4023,53 @@ function t(suffix) {
4016
4023
  return `${getConfig().toolPrefix}_${suffix}`;
4017
4024
  }
4018
4025
 
4026
+ // src/lib/source-layout.ts
4027
+ init_config();
4028
+ function normalizeDir(raw) {
4029
+ if (typeof raw !== "string") return null;
4030
+ const posix = raw.replace(/\\/g, "/");
4031
+ if (posix.startsWith("/") || /^[A-Za-z]:\//.test(posix)) return null;
4032
+ const parts = posix.split("/").filter((p) => p !== "" && p !== ".");
4033
+ if (parts.some((p) => p === "..")) return null;
4034
+ if (parts.length === 0) return ".";
4035
+ return parts.join("/");
4036
+ }
4037
+ function declaredLanguageSourceDirs() {
4038
+ const languages = getConfig().framework.languages;
4039
+ if (!languages) return [];
4040
+ const out = [];
4041
+ for (const entry of Object.values(languages)) {
4042
+ if (Array.isArray(entry.source_dirs)) out.push(...entry.source_dirs);
4043
+ }
4044
+ return out;
4045
+ }
4046
+ function getSourceLayout() {
4047
+ const config = getConfig();
4048
+ const paths = config.paths;
4049
+ const declared = [
4050
+ paths.source,
4051
+ ...paths.monorepo_roots ?? [],
4052
+ ...declaredLanguageSourceDirs()
4053
+ ];
4054
+ const normalized = declared.map(normalizeDir).filter((d) => d !== null);
4055
+ const includesRoot = normalized.includes(".");
4056
+ const sourceDirs = includesRoot ? [] : [...new Set(normalized)].sort();
4057
+ const source = normalizeDir(paths.source) ?? ".";
4058
+ const under = (child) => source === "." ? child : `${source}/${child}`;
4059
+ return {
4060
+ sourceDirs,
4061
+ includesRoot,
4062
+ extensions: getResolvedPaths().extensions,
4063
+ pagesDir: normalizeDir(paths.pages ?? under("app")) ?? under("app"),
4064
+ componentsDir: normalizeDir(paths.components ?? under("components")) ?? under("components")
4065
+ };
4066
+ }
4067
+ function isUnderSourceDir(path, layout = getSourceLayout()) {
4068
+ if (normalizeDir(path) === null) return false;
4069
+ if (layout.includesRoot) return true;
4070
+ return layout.sourceDirs.some((d) => path.startsWith(`${d}/`));
4071
+ }
4072
+
4019
4073
  // src/middleware-tree.ts
4020
4074
  function isInMiddlewareTree(dataDb, file) {
4021
4075
  const result = dataDb.prepare(`SELECT 1 FROM ${t("middleware_tree")} WHERE file = ?`).get(file);
@@ -4062,6 +4116,20 @@ function writeHookContext(hookEventName, message) {
4062
4116
 
4063
4117
  // src/hooks/post-edit-context.ts
4064
4118
  init_hook_failure_signal();
4119
+
4120
+ // src/hooks/lib/is-direct-invocation.ts
4121
+ import { pathToFileURL } from "url";
4122
+ function isDirectInvocation(moduleUrl) {
4123
+ const entry = process.argv[1];
4124
+ if (!entry) return false;
4125
+ try {
4126
+ return moduleUrl === pathToFileURL(entry).href;
4127
+ } catch {
4128
+ return false;
4129
+ }
4130
+ }
4131
+
4132
+ // src/hooks/post-edit-context.ts
4065
4133
  var HOOK_EVENT = "PostToolUse";
4066
4134
  async function main() {
4067
4135
  try {
@@ -4074,7 +4142,7 @@ async function main() {
4074
4142
  }
4075
4143
  const root = getProjectRoot();
4076
4144
  const rel = filePath.startsWith(root + "/") ? filePath.slice(root.length + 1) : filePath;
4077
- if (!rel.startsWith("src/") && !rel.endsWith(".py")) {
4145
+ if (!isUnderSourceDir(rel) && !rel.endsWith(".py")) {
4078
4146
  process.exit(0);
4079
4147
  return;
4080
4148
  }
@@ -4117,4 +4185,6 @@ function readStdin() {
4117
4185
  setTimeout(() => resolve5(data), 3e3);
4118
4186
  });
4119
4187
  }
4120
- main();
4188
+ if (isDirectInvocation(import.meta.url)) {
4189
+ main();
4190
+ }
@@ -1173,6 +1173,13 @@ var init_config = __esm({
1173
1173
  });
1174
1174
  LanguageFrameworkEntrySchema = z2.object({
1175
1175
  framework: z2.string().optional(),
1176
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1177
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1178
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1179
+ // derives the index builders' candidate set from it, so it is typed here rather than
1180
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1181
+ // from silently contributing `undefined` to a path predicate.
1182
+ source_dirs: z2.array(z2.string()).optional(),
1176
1183
  test_framework: z2.string().optional(),
1177
1184
  test: z2.string().optional(),
1178
1185
  runtime: z2.string().optional(),
@@ -4471,6 +4478,9 @@ function enforceSeverityFloors(configWeights, defaults) {
4471
4478
  // src/lib/sql-table-names.ts
4472
4479
  init_config();
4473
4480
 
4481
+ // src/lib/source-layout.ts
4482
+ init_config();
4483
+
4474
4484
  // src/import-resolver.ts
4475
4485
  function resolveImportPath(specifier, fromFile) {
4476
4486
  if (!specifier.startsWith(".") && !specifier.startsWith("@/")) {
@@ -5046,6 +5056,18 @@ function mapMemoryTypeToObservationType(memoryType) {
5046
5056
  }
5047
5057
  }
5048
5058
 
5059
+ // src/hooks/lib/is-direct-invocation.ts
5060
+ import { pathToFileURL } from "url";
5061
+ function isDirectInvocation(moduleUrl) {
5062
+ const entry = process.argv[1];
5063
+ if (!entry) return false;
5064
+ try {
5065
+ return moduleUrl === pathToFileURL(entry).href;
5066
+ } catch {
5067
+ return false;
5068
+ }
5069
+ }
5070
+
5049
5071
  // src/hooks/post-tool-use.ts
5050
5072
  var _yamlParser = null;
5051
5073
  var parseYaml3 = (content) => {
@@ -5384,4 +5406,6 @@ function checkMemoryFileIntegrity(filePath) {
5384
5406
  }
5385
5407
  return issues;
5386
5408
  }
5387
- main();
5409
+ if (isDirectInvocation(import.meta.url)) {
5410
+ main();
5411
+ }
@@ -1167,6 +1167,13 @@ var init_config = __esm({
1167
1167
  });
1168
1168
  LanguageFrameworkEntrySchema = z2.object({
1169
1169
  framework: z2.string().optional(),
1170
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1171
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1172
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1173
+ // derives the index builders' candidate set from it, so it is typed here rather than
1174
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1175
+ // from silently contributing `undefined` to a path predicate.
1176
+ source_dirs: z2.array(z2.string()).optional(),
1170
1177
  test_framework: z2.string().optional(),
1171
1178
  test: z2.string().optional(),
1172
1179
  runtime: z2.string().optional(),
@@ -4010,6 +4017,20 @@ function logAuditEntry(db, entry) {
4010
4017
 
4011
4018
  // src/hooks/pre-compact.ts
4012
4019
  init_hook_failure_signal();
4020
+
4021
+ // src/hooks/lib/is-direct-invocation.ts
4022
+ import { pathToFileURL } from "url";
4023
+ function isDirectInvocation(moduleUrl) {
4024
+ const entry = process.argv[1];
4025
+ if (!entry) return false;
4026
+ try {
4027
+ return moduleUrl === pathToFileURL(entry).href;
4028
+ } catch {
4029
+ return false;
4030
+ }
4031
+ }
4032
+
4033
+ // src/hooks/pre-compact.ts
4013
4034
  async function main() {
4014
4035
  try {
4015
4036
  const input = await readStdin();
@@ -4116,4 +4137,6 @@ function readStdin() {
4116
4137
  setTimeout(() => resolve5(data), 3e3);
4117
4138
  });
4118
4139
  }
4119
- main();
4140
+ if (isDirectInvocation(import.meta.url)) {
4141
+ main();
4142
+ }
@@ -1167,6 +1167,13 @@ var init_config = __esm({
1167
1167
  });
1168
1168
  LanguageFrameworkEntrySchema = z2.object({
1169
1169
  framework: z2.string().optional(),
1170
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1171
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1172
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1173
+ // derives the index builders' candidate set from it, so it is typed here rather than
1174
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1175
+ // from silently contributing `undefined` to a path predicate.
1176
+ source_dirs: z2.array(z2.string()).optional(),
1170
1177
  test_framework: z2.string().optional(),
1171
1178
  test: z2.string().optional(),
1172
1179
  runtime: z2.string().optional(),
@@ -4084,6 +4091,53 @@ function getFeatureImpact(db, filePaths) {
4084
4091
  // src/hooks/pre-delete-check.ts
4085
4092
  init_config();
4086
4093
 
4094
+ // src/lib/source-layout.ts
4095
+ init_config();
4096
+ function normalizeDir(raw) {
4097
+ if (typeof raw !== "string") return null;
4098
+ const posix = raw.replace(/\\/g, "/");
4099
+ if (posix.startsWith("/") || /^[A-Za-z]:\//.test(posix)) return null;
4100
+ const parts = posix.split("/").filter((p) => p !== "" && p !== ".");
4101
+ if (parts.some((p) => p === "..")) return null;
4102
+ if (parts.length === 0) return ".";
4103
+ return parts.join("/");
4104
+ }
4105
+ function declaredLanguageSourceDirs() {
4106
+ const languages = getConfig().framework.languages;
4107
+ if (!languages) return [];
4108
+ const out = [];
4109
+ for (const entry of Object.values(languages)) {
4110
+ if (Array.isArray(entry.source_dirs)) out.push(...entry.source_dirs);
4111
+ }
4112
+ return out;
4113
+ }
4114
+ function getSourceLayout() {
4115
+ const config = getConfig();
4116
+ const paths = config.paths;
4117
+ const declared = [
4118
+ paths.source,
4119
+ ...paths.monorepo_roots ?? [],
4120
+ ...declaredLanguageSourceDirs()
4121
+ ];
4122
+ const normalized = declared.map(normalizeDir).filter((d) => d !== null);
4123
+ const includesRoot = normalized.includes(".");
4124
+ const sourceDirs = includesRoot ? [] : [...new Set(normalized)].sort();
4125
+ const source = normalizeDir(paths.source) ?? ".";
4126
+ const under = (child) => source === "." ? child : `${source}/${child}`;
4127
+ return {
4128
+ sourceDirs,
4129
+ includesRoot,
4130
+ extensions: getResolvedPaths().extensions,
4131
+ pagesDir: normalizeDir(paths.pages ?? under("app")) ?? under("app"),
4132
+ componentsDir: normalizeDir(paths.components ?? under("components")) ?? under("components")
4133
+ };
4134
+ }
4135
+ function isUnderSourceDir(path, layout = getSourceLayout()) {
4136
+ if (normalizeDir(path) === null) return false;
4137
+ if (layout.includesRoot) return true;
4138
+ return layout.sourceDirs.some((d) => path.startsWith(`${d}/`));
4139
+ }
4140
+
4087
4141
  // src/hooks/lib/write-hook-message.ts
4088
4142
  var HOOK_EVENTS = [
4089
4143
  "UserPromptSubmit",
@@ -4121,6 +4175,20 @@ function writeHookContext(hookEventName, message) {
4121
4175
 
4122
4176
  // src/hooks/pre-delete-check.ts
4123
4177
  init_hook_failure_signal();
4178
+
4179
+ // src/hooks/lib/is-direct-invocation.ts
4180
+ import { pathToFileURL } from "url";
4181
+ function isDirectInvocation(moduleUrl) {
4182
+ const entry = process.argv[1];
4183
+ if (!entry) return false;
4184
+ try {
4185
+ return moduleUrl === pathToFileURL(entry).href;
4186
+ } catch {
4187
+ return false;
4188
+ }
4189
+ }
4190
+
4191
+ // src/hooks/pre-delete-check.ts
4124
4192
  var HOOK_EVENT = "PreToolUse";
4125
4193
  var PROJECT_ROOT2 = getProjectRoot();
4126
4194
  var KNOWLEDGE_PROTECTED_FILES = [
@@ -4171,8 +4239,8 @@ function extractDeletedFiles(input) {
4171
4239
  if (rmMatch) {
4172
4240
  const paths = rmMatch[1].split(/\s+/).filter((p) => !p.startsWith("-"));
4173
4241
  for (const p of paths) {
4174
- const relPath = p.startsWith("src/") ? p : p.replace(PROJECT_ROOT2 + "/", "");
4175
- if (relPath.startsWith("src/") || relPath.endsWith(".py")) {
4242
+ const relPath = isUnderSourceDir(p) ? p : p.replace(PROJECT_ROOT2 + "/", "");
4243
+ if (isUnderSourceDir(relPath) || relPath.endsWith(".py")) {
4176
4244
  files.push(relPath);
4177
4245
  }
4178
4246
  }
@@ -4182,7 +4250,7 @@ function extractDeletedFiles(input) {
4182
4250
  const content = input.tool_input.content || "";
4183
4251
  if (content.trim().length === 0) {
4184
4252
  const relPath = input.tool_input.file_path.replace(PROJECT_ROOT2 + "/", "");
4185
- if (relPath.startsWith("src/") || relPath.endsWith(".py")) {
4253
+ if (isUnderSourceDir(relPath) || relPath.endsWith(".py")) {
4186
4254
  files.push(relPath);
4187
4255
  }
4188
4256
  }
@@ -4284,7 +4352,7 @@ function readStdin() {
4284
4352
  setTimeout(() => resolve5(data), 400);
4285
4353
  });
4286
4354
  }
4287
- if (process.argv[1]?.endsWith("pre-delete-check.js") || process.argv[1]?.endsWith("pre-delete-check")) {
4355
+ if (isDirectInvocation(import.meta.url)) {
4288
4356
  main();
4289
4357
  }
4290
4358
  export {
@@ -1167,6 +1167,13 @@ var init_config = __esm({
1167
1167
  });
1168
1168
  LanguageFrameworkEntrySchema = z2.object({
1169
1169
  framework: z2.string().optional(),
1170
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1171
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1172
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1173
+ // derives the index builders' candidate set from it, so it is typed here rather than
1174
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1175
+ // from silently contributing `undefined` to a path predicate.
1176
+ source_dirs: z2.array(z2.string()).optional(),
1170
1177
  test_framework: z2.string().optional(),
1171
1178
  test: z2.string().optional(),
1172
1179
  runtime: z2.string().optional(),
@@ -4022,6 +4029,20 @@ function writeHookContext(hookEventName, message) {
4022
4029
 
4023
4030
  // src/hooks/security-gate.ts
4024
4031
  init_hook_failure_signal();
4032
+
4033
+ // src/hooks/lib/is-direct-invocation.ts
4034
+ import { pathToFileURL } from "url";
4035
+ function isDirectInvocation(moduleUrl) {
4036
+ const entry = process.argv[1];
4037
+ if (!entry) return false;
4038
+ try {
4039
+ return moduleUrl === pathToFileURL(entry).href;
4040
+ } catch {
4041
+ return false;
4042
+ }
4043
+ }
4044
+
4045
+ // src/hooks/security-gate.ts
4025
4046
  var HOOK_EVENT = "PreToolUse";
4026
4047
  var DANGEROUS_BASH_PATTERNS = [
4027
4048
  // BLOCK — destructive and irreversible, or arbitrary remote code execution.
@@ -4161,7 +4182,7 @@ function readStdin() {
4161
4182
  setTimeout(() => resolve5(data), 400);
4162
4183
  });
4163
4184
  }
4164
- if (process.argv[1]?.endsWith("security-gate.js") || process.argv[1]?.endsWith("security-gate")) {
4185
+ if (isDirectInvocation(import.meta.url)) {
4165
4186
  main();
4166
4187
  }
4167
4188
 
@@ -4263,6 +4284,55 @@ function getFeatureImpact(db, filePaths) {
4263
4284
 
4264
4285
  // src/hooks/pre-delete-check.ts
4265
4286
  init_config();
4287
+
4288
+ // src/lib/source-layout.ts
4289
+ init_config();
4290
+ function normalizeDir(raw) {
4291
+ if (typeof raw !== "string") return null;
4292
+ const posix = raw.replace(/\\/g, "/");
4293
+ if (posix.startsWith("/") || /^[A-Za-z]:\//.test(posix)) return null;
4294
+ const parts = posix.split("/").filter((p) => p !== "" && p !== ".");
4295
+ if (parts.some((p) => p === "..")) return null;
4296
+ if (parts.length === 0) return ".";
4297
+ return parts.join("/");
4298
+ }
4299
+ function declaredLanguageSourceDirs() {
4300
+ const languages = getConfig().framework.languages;
4301
+ if (!languages) return [];
4302
+ const out = [];
4303
+ for (const entry of Object.values(languages)) {
4304
+ if (Array.isArray(entry.source_dirs)) out.push(...entry.source_dirs);
4305
+ }
4306
+ return out;
4307
+ }
4308
+ function getSourceLayout() {
4309
+ const config = getConfig();
4310
+ const paths = config.paths;
4311
+ const declared = [
4312
+ paths.source,
4313
+ ...paths.monorepo_roots ?? [],
4314
+ ...declaredLanguageSourceDirs()
4315
+ ];
4316
+ const normalized = declared.map(normalizeDir).filter((d) => d !== null);
4317
+ const includesRoot = normalized.includes(".");
4318
+ const sourceDirs = includesRoot ? [] : [...new Set(normalized)].sort();
4319
+ const source = normalizeDir(paths.source) ?? ".";
4320
+ const under = (child) => source === "." ? child : `${source}/${child}`;
4321
+ return {
4322
+ sourceDirs,
4323
+ includesRoot,
4324
+ extensions: getResolvedPaths().extensions,
4325
+ pagesDir: normalizeDir(paths.pages ?? under("app")) ?? under("app"),
4326
+ componentsDir: normalizeDir(paths.components ?? under("components")) ?? under("components")
4327
+ };
4328
+ }
4329
+ function isUnderSourceDir(path, layout = getSourceLayout()) {
4330
+ if (normalizeDir(path) === null) return false;
4331
+ if (layout.includesRoot) return true;
4332
+ return layout.sourceDirs.some((d) => path.startsWith(`${d}/`));
4333
+ }
4334
+
4335
+ // src/hooks/pre-delete-check.ts
4266
4336
  init_hook_failure_signal();
4267
4337
  var HOOK_EVENT2 = "PreToolUse";
4268
4338
  var PROJECT_ROOT2 = getProjectRoot();
@@ -4314,8 +4384,8 @@ function extractDeletedFiles(input) {
4314
4384
  if (rmMatch) {
4315
4385
  const paths = rmMatch[1].split(/\s+/).filter((p) => !p.startsWith("-"));
4316
4386
  for (const p of paths) {
4317
- const relPath = p.startsWith("src/") ? p : p.replace(PROJECT_ROOT2 + "/", "");
4318
- if (relPath.startsWith("src/") || relPath.endsWith(".py")) {
4387
+ const relPath = isUnderSourceDir(p) ? p : p.replace(PROJECT_ROOT2 + "/", "");
4388
+ if (isUnderSourceDir(relPath) || relPath.endsWith(".py")) {
4319
4389
  files.push(relPath);
4320
4390
  }
4321
4391
  }
@@ -4325,7 +4395,7 @@ function extractDeletedFiles(input) {
4325
4395
  const content = input.tool_input.content || "";
4326
4396
  if (content.trim().length === 0) {
4327
4397
  const relPath = input.tool_input.file_path.replace(PROJECT_ROOT2 + "/", "");
4328
- if (relPath.startsWith("src/") || relPath.endsWith(".py")) {
4398
+ if (isUnderSourceDir(relPath) || relPath.endsWith(".py")) {
4329
4399
  files.push(relPath);
4330
4400
  }
4331
4401
  }
@@ -4427,7 +4497,7 @@ function readStdin2() {
4427
4497
  setTimeout(() => resolve5(data), 400);
4428
4498
  });
4429
4499
  }
4430
- if (process.argv[1]?.endsWith("pre-delete-check.js") || process.argv[1]?.endsWith("pre-delete-check")) {
4500
+ if (isDirectInvocation(import.meta.url)) {
4431
4501
  main2();
4432
4502
  }
4433
4503
 
@@ -4525,4 +4595,6 @@ async function main3() {
4525
4595
  }
4526
4596
  process.exit(EXIT_ALLOW);
4527
4597
  }
4528
- main3();
4598
+ if (isDirectInvocation(import.meta.url)) {
4599
+ main3();
4600
+ }
@@ -1167,6 +1167,13 @@ var init_config = __esm({
1167
1167
  });
1168
1168
  LanguageFrameworkEntrySchema = z2.object({
1169
1169
  framework: z2.string().optional(),
1170
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1171
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1172
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1173
+ // derives the index builders' candidate set from it, so it is typed here rather than
1174
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1175
+ // from silently contributing `undefined` to a path predicate.
1176
+ source_dirs: z2.array(z2.string()).optional(),
1170
1177
  test_framework: z2.string().optional(),
1171
1178
  test: z2.string().optional(),
1172
1179
  runtime: z2.string().optional(),
@@ -4086,6 +4093,20 @@ function toolResponseText(raw) {
4086
4093
  // src/hooks/quality-event.ts
4087
4094
  init_hook_failure_signal();
4088
4095
  init_timestamps();
4096
+
4097
+ // src/hooks/lib/is-direct-invocation.ts
4098
+ import { pathToFileURL } from "url";
4099
+ function isDirectInvocation(moduleUrl) {
4100
+ const entry = process.argv[1];
4101
+ if (!entry) return false;
4102
+ try {
4103
+ return moduleUrl === pathToFileURL(entry).href;
4104
+ } catch {
4105
+ return false;
4106
+ }
4107
+ }
4108
+
4109
+ // src/hooks/quality-event.ts
4089
4110
  var TEST_FAILURE_PATTERNS = [
4090
4111
  /\bFAIL\b/,
4091
4112
  /✗/,
@@ -4174,4 +4195,6 @@ function readStdin() {
4174
4195
  setTimeout(() => resolve5(data), 3e3);
4175
4196
  });
4176
4197
  }
4177
- main();
4198
+ if (isDirectInvocation(import.meta.url)) {
4199
+ main();
4200
+ }
@@ -697,6 +697,13 @@ var init_config = __esm({
697
697
  });
698
698
  LanguageFrameworkEntrySchema = z2.object({
699
699
  framework: z2.string().optional(),
700
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
701
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
702
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
703
+ // derives the index builders' candidate set from it, so it is typed here rather than
704
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
705
+ // from silently contributing `undefined` to a path predicate.
706
+ source_dirs: z2.array(z2.string()).optional(),
700
707
  test_framework: z2.string().optional(),
701
708
  test: z2.string().optional(),
702
709
  runtime: z2.string().optional(),
@@ -4027,6 +4034,20 @@ function writeHookContext(hookEventName, message) {
4027
4034
 
4028
4035
  // src/hooks/rule-enforcement-pipeline.ts
4029
4036
  init_hook_failure_signal();
4037
+
4038
+ // src/hooks/lib/is-direct-invocation.ts
4039
+ import { pathToFileURL } from "url";
4040
+ function isDirectInvocation(moduleUrl) {
4041
+ const entry = process.argv[1];
4042
+ if (!entry) return false;
4043
+ try {
4044
+ return moduleUrl === pathToFileURL(entry).href;
4045
+ } catch {
4046
+ return false;
4047
+ }
4048
+ }
4049
+
4050
+ // src/hooks/rule-enforcement-pipeline.ts
4030
4051
  var HOOK_EVENT = "PostToolUse";
4031
4052
  async function main() {
4032
4053
  try {
@@ -4142,4 +4163,6 @@ function readStdin() {
4142
4163
  setTimeout(() => resolve6(data), 3e3);
4143
4164
  });
4144
4165
  }
4145
- main();
4166
+ if (isDirectInvocation(import.meta.url)) {
4167
+ main();
4168
+ }
@@ -1167,6 +1167,13 @@ var init_config = __esm({
1167
1167
  });
1168
1168
  LanguageFrameworkEntrySchema = z2.object({
1169
1169
  framework: z2.string().optional(),
1170
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1171
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1172
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1173
+ // derives the index builders' candidate set from it, so it is typed here rather than
1174
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1175
+ // from silently contributing `undefined` to a path predicate.
1176
+ source_dirs: z2.array(z2.string()).optional(),
1170
1177
  test_framework: z2.string().optional(),
1171
1178
  test: z2.string().optional(),
1172
1179
  runtime: z2.string().optional(),
@@ -4022,6 +4029,20 @@ function writeHookContext(hookEventName, message) {
4022
4029
 
4023
4030
  // src/hooks/security-gate.ts
4024
4031
  init_hook_failure_signal();
4032
+
4033
+ // src/hooks/lib/is-direct-invocation.ts
4034
+ import { pathToFileURL } from "url";
4035
+ function isDirectInvocation(moduleUrl) {
4036
+ const entry = process.argv[1];
4037
+ if (!entry) return false;
4038
+ try {
4039
+ return moduleUrl === pathToFileURL(entry).href;
4040
+ } catch {
4041
+ return false;
4042
+ }
4043
+ }
4044
+
4045
+ // src/hooks/security-gate.ts
4025
4046
  var HOOK_EVENT = "PreToolUse";
4026
4047
  var DANGEROUS_BASH_PATTERNS = [
4027
4048
  // BLOCK — destructive and irreversible, or arbitrary remote code execution.
@@ -4161,7 +4182,7 @@ function readStdin() {
4161
4182
  setTimeout(() => resolve5(data), 400);
4162
4183
  });
4163
4184
  }
4164
- if (process.argv[1]?.endsWith("security-gate.js") || process.argv[1]?.endsWith("security-gate")) {
4185
+ if (isDirectInvocation(import.meta.url)) {
4165
4186
  main();
4166
4187
  }
4167
4188
  export {
@@ -1167,6 +1167,13 @@ var init_config = __esm({
1167
1167
  });
1168
1168
  LanguageFrameworkEntrySchema = z2.object({
1169
1169
  framework: z2.string().optional(),
1170
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1171
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1172
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1173
+ // derives the index builders' candidate set from it, so it is typed here rather than
1174
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1175
+ // from silently contributing `undefined` to a path predicate.
1176
+ source_dirs: z2.array(z2.string()).optional(),
1170
1177
  test_framework: z2.string().optional(),
1171
1178
  test: z2.string().optional(),
1172
1179
  runtime: z2.string().optional(),
@@ -7361,6 +7368,20 @@ async function runConsolidation(db, opts = {}) {
7361
7368
 
7362
7369
  // src/hooks/session-end.ts
7363
7370
  init_hook_failure_signal();
7371
+
7372
+ // src/hooks/lib/is-direct-invocation.ts
7373
+ import { pathToFileURL } from "url";
7374
+ function isDirectInvocation(moduleUrl) {
7375
+ const entry = process.argv[1];
7376
+ if (!entry) return false;
7377
+ try {
7378
+ return moduleUrl === pathToFileURL(entry).href;
7379
+ } catch {
7380
+ return false;
7381
+ }
7382
+ }
7383
+
7384
+ // src/hooks/session-end.ts
7364
7385
  async function main() {
7365
7386
  try {
7366
7387
  const input = await readStdin();
@@ -7720,4 +7741,6 @@ function readStdin() {
7720
7741
  setTimeout(() => resolve8(data), 5e3);
7721
7742
  });
7722
7743
  }
7723
- main();
7744
+ if (isDirectInvocation(import.meta.url)) {
7745
+ main();
7746
+ }
@@ -1190,6 +1190,13 @@ var init_config = __esm({
1190
1190
  });
1191
1191
  LanguageFrameworkEntrySchema = z2.object({
1192
1192
  framework: z2.string().optional(),
1193
+ // `source_dirs` is emitted by `init` (commands/init.ts:417) and existence-checked
1194
+ // by config validation (init.ts:868-876), but until 2026-08-14 it survived only via
1195
+ // `.passthrough()` — declared in the file, untyped in the schema. `lib/source-layout.ts`
1196
+ // derives the index builders' candidate set from it, so it is typed here rather than
1197
+ // read as an unknown: a consumer that has to shape-check its own SoT is one branch away
1198
+ // from silently contributing `undefined` to a path predicate.
1199
+ source_dirs: z2.array(z2.string()).optional(),
1193
1200
  test_framework: z2.string().optional(),
1194
1201
  test: z2.string().optional(),
1195
1202
  runtime: z2.string().optional(),
@@ -14188,6 +14195,20 @@ function checkWindows(pid) {
14188
14195
 
14189
14196
  // src/hooks/session-start.ts
14190
14197
  init_hook_failure_signal();
14198
+
14199
+ // src/hooks/lib/is-direct-invocation.ts
14200
+ import { pathToFileURL } from "url";
14201
+ function isDirectInvocation(moduleUrl) {
14202
+ const entry = process.argv[1];
14203
+ if (!entry) return false;
14204
+ try {
14205
+ return moduleUrl === pathToFileURL(entry).href;
14206
+ } catch {
14207
+ return false;
14208
+ }
14209
+ }
14210
+
14211
+ // src/hooks/session-start.ts
14191
14212
  async function main() {
14192
14213
  try {
14193
14214
  const input = await readStdin();
@@ -14546,7 +14567,9 @@ function formatAge(ms) {
14546
14567
  const hr = Math.round(min / 60);
14547
14568
  return `${hr}h`;
14548
14569
  }
14549
- main();
14570
+ if (isDirectInvocation(import.meta.url)) {
14571
+ main();
14572
+ }
14550
14573
  /*! Bundled license information:
14551
14574
 
14552
14575
  is-extglob/index.js: