devworkspace 0.2.0 → 0.2.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +4 -3
  3. package/dist/agents/claude/content.js +3 -2
  4. package/dist/agents/claude/content.js.map +1 -1
  5. package/dist/cli/args.d.ts +16 -0
  6. package/dist/cli/args.js +5 -0
  7. package/dist/cli/args.js.map +1 -1
  8. package/dist/cli/help.js +30 -7
  9. package/dist/cli/help.js.map +1 -1
  10. package/dist/cli/render.d.ts +7 -1
  11. package/dist/cli/render.js +70 -13
  12. package/dist/cli/render.js.map +1 -1
  13. package/dist/cli/run.js +47 -8
  14. package/dist/cli/run.js.map +1 -1
  15. package/dist/config/schemas.d.ts +12 -1
  16. package/dist/config/schemas.js +12 -0
  17. package/dist/config/schemas.js.map +1 -1
  18. package/dist/discovery/commands.d.ts +34 -3
  19. package/dist/discovery/commands.js +109 -33
  20. package/dist/discovery/commands.js.map +1 -1
  21. package/dist/discovery/detect.d.ts +23 -0
  22. package/dist/discovery/detect.js +113 -48
  23. package/dist/discovery/detect.js.map +1 -1
  24. package/dist/discovery/docs.d.ts +10 -0
  25. package/dist/discovery/docs.js +52 -0
  26. package/dist/discovery/docs.js.map +1 -0
  27. package/dist/discovery/entrypoints.d.ts +20 -0
  28. package/dist/discovery/entrypoints.js +67 -0
  29. package/dist/discovery/entrypoints.js.map +1 -0
  30. package/dist/integrations/adapters/graphify.js +46 -8
  31. package/dist/integrations/adapters/graphify.js.map +1 -1
  32. package/dist/integrations/manager.js +14 -1
  33. package/dist/integrations/manager.js.map +1 -1
  34. package/dist/integrations/persistentPath.d.ts +20 -0
  35. package/dist/integrations/persistentPath.js +47 -0
  36. package/dist/integrations/persistentPath.js.map +1 -0
  37. package/dist/integrations/types.d.ts +6 -0
  38. package/dist/integrations/types.js.map +1 -1
  39. package/dist/knowledge/facts.d.ts +59 -2
  40. package/dist/knowledge/facts.js +115 -17
  41. package/dist/knowledge/facts.js.map +1 -1
  42. package/dist/prompts/onboarding.js +9 -6
  43. package/dist/prompts/onboarding.js.map +1 -1
  44. package/dist/services/analysis.d.ts +13 -1
  45. package/dist/services/analysis.js +23 -18
  46. package/dist/services/analysis.js.map +1 -1
  47. package/dist/services/doctor.js +92 -7
  48. package/dist/services/doctor.js.map +1 -1
  49. package/dist/services/knowledge.d.ts +17 -0
  50. package/dist/services/knowledge.js +28 -2
  51. package/dist/services/knowledge.js.map +1 -1
  52. package/dist/services/refresh.js +6 -6
  53. package/dist/services/refresh.js.map +1 -1
  54. package/dist/services/status.d.ts +12 -2
  55. package/dist/services/status.js +11 -9
  56. package/dist/services/status.js.map +1 -1
  57. package/dist/services/tasks.d.ts +2 -0
  58. package/dist/services/tasks.js +20 -12
  59. package/dist/services/tasks.js.map +1 -1
  60. package/dist/services/verify.d.ts +47 -0
  61. package/dist/services/verify.js +172 -0
  62. package/dist/services/verify.js.map +1 -0
  63. package/dist/tasks/routing.js +8 -3
  64. package/dist/tasks/routing.js.map +1 -1
  65. package/dist/tasks/task.d.ts +49 -5
  66. package/dist/tasks/task.js +68 -11
  67. package/dist/tasks/task.js.map +1 -1
  68. package/dist/verification/safety.d.ts +38 -0
  69. package/dist/verification/safety.js +120 -0
  70. package/dist/verification/safety.js.map +1 -0
  71. package/dist/verification/scope.d.ts +19 -0
  72. package/dist/verification/scope.js +119 -0
  73. package/dist/verification/scope.js.map +1 -0
  74. package/docs/integrations.md +1 -1
  75. package/docs/knowledge.md +2 -0
  76. package/docs/testing.md +29 -2
  77. package/docs/troubleshooting.md +4 -1
  78. package/package.json +1 -1
@@ -2,6 +2,8 @@ import path from 'node:path';
2
2
  import { safeReadText } from '../security/files.js';
3
3
  import { isSensitiveFile } from '../security/files.js';
4
4
  import { buildContract } from './commands.js';
5
+ import { detectDocs, MAX_DOCS } from './docs.js';
6
+ import { discoverEntryPoints } from './entrypoints.js';
5
7
  const EXT_LANG = {
6
8
  '.ts': 'TypeScript',
7
9
  '.tsx': 'TypeScript',
@@ -145,6 +147,8 @@ export async function readPackageJson(root, rel) {
145
147
  packageManagerField: typeof j.packageManager === 'string' ? j.packageManager : undefined,
146
148
  hasTypes: 'typescript' in deps,
147
149
  type: typeof j.type === 'string' ? j.type : undefined,
150
+ main: typeof j.main === 'string' ? j.main : undefined,
151
+ bin: typeof j.bin === 'string' ? [j.bin] : Object.values(strMap(j.bin)),
148
152
  };
149
153
  }
150
154
  function nodeFrameworks(pkg) {
@@ -221,6 +225,71 @@ function languagesFrom(byExt) {
221
225
  }
222
226
  return [...acc.entries()].map(([name, files]) => ({ name, files })).sort((a, b) => b.files - a.files || a.name.localeCompare(b.name));
223
227
  }
228
+ const LOCKFILES = [
229
+ ['pnpm-lock.yaml', 'pnpm'],
230
+ ['yarn.lock', 'yarn'],
231
+ ['bun.lockb', 'bun'],
232
+ ['bun.lock', 'bun'],
233
+ ['package-lock.json', 'npm'],
234
+ ['npm-shrinkwrap.json', 'npm'],
235
+ ];
236
+ const MAX_NODE_PACKAGES = 200;
237
+ const MAX_MANIFEST_DEPTH = 5;
238
+ /** A package.json that only sets {"type":"module"} (a marker file) is not a package. */
239
+ function isRealManifest(p) {
240
+ return !!p.name || Object.keys(p.scripts).length > 0 || Object.keys(p.deps).length > 0 || p.workspaces.length > 0;
241
+ }
242
+ function lockfilePm(files, dir) {
243
+ for (const [lock, pm] of LOCKFILES)
244
+ if (files.has(dir ? `${dir}/${lock}` : lock))
245
+ return pm;
246
+ return null;
247
+ }
248
+ /**
249
+ * Find every Node.js package, not just the root one. Each package gets its own package manager from its own lockfile
250
+ * (falling back to the packageManager field, then the root lockfile, then npm). No script is ever executed.
251
+ */
252
+ export async function discoverNodePackages(root, files) {
253
+ const manifests = [...files]
254
+ .filter((f) => path.posix.basename(f) === 'package.json' && !isAuxPath(f) && f.split('/').length <= MAX_MANIFEST_DEPTH)
255
+ .sort((a, b) => a.split('/').length - b.split('/').length || a.localeCompare(b))
256
+ .slice(0, MAX_NODE_PACKAGES);
257
+ const rootLockPm = lockfilePm(files, '');
258
+ const packages = [];
259
+ const unparsable = [];
260
+ for (const manifest of manifests) {
261
+ const pkg = await readPackageJson(root, manifest);
262
+ if (!pkg) {
263
+ unparsable.push(manifest);
264
+ continue;
265
+ }
266
+ if (!isRealManifest(pkg))
267
+ continue;
268
+ const dir = path.posix.dirname(manifest) === '.' ? '' : path.posix.dirname(manifest);
269
+ const own = lockfilePm(files, dir);
270
+ const field = pkg.packageManagerField?.split('@')[0] ?? null;
271
+ let packageManager;
272
+ let pmSource;
273
+ if (own) {
274
+ packageManager = own;
275
+ pmSource = 'lockfile';
276
+ }
277
+ else if (field) {
278
+ packageManager = field;
279
+ pmSource = 'packageManager field';
280
+ }
281
+ else if (rootLockPm && dir !== '') {
282
+ packageManager = rootLockPm;
283
+ pmSource = 'inherited from root';
284
+ }
285
+ else {
286
+ packageManager = 'npm';
287
+ pmSource = 'default';
288
+ }
289
+ packages.push({ dir, pkg, packageManager, hasTsconfig: files.has(dir ? `${dir}/tsconfig.json` : 'tsconfig.json'), manifest, pmSource });
290
+ }
291
+ return { packages, unparsable };
292
+ }
224
293
  export async function detectProject(input) {
225
294
  const { root, scan } = input;
226
295
  const files = scan.files;
@@ -232,27 +301,23 @@ export async function detectProject(input) {
232
301
  if (!frameworks.has(d.name))
233
302
  frameworks.set(d.name, d);
234
303
  };
235
- // Node / JS
236
- const rootPkg = has('package.json') ? await readPackageJson(root, 'package.json') : null;
237
- if (has('package.json') && !rootPkg)
238
- warnings.push('package.json exists but could not be parsed.');
239
- if (rootPkg) {
304
+ // Node / JS: every package.json, not only the one at the root
305
+ const { packages: nodePkgs, unparsable } = await discoverNodePackages(root, files);
306
+ for (const m of unparsable.slice(0, 5))
307
+ warnings.push(`${m} exists but could not be parsed.`);
308
+ const rootNode = nodePkgs.find((p) => p.dir === '');
309
+ const rootPkg = rootNode?.pkg ?? null;
310
+ if (nodePkgs.length > 0) {
240
311
  ecosystems.add('node');
241
- nodeFrameworks(rootPkg).forEach(addFw);
312
+ for (const p of nodePkgs)
313
+ nodeFrameworks(p.pkg).forEach(addFw);
242
314
  }
243
315
  let packageManager = null;
244
- if (has('pnpm-lock.yaml'))
245
- packageManager = 'pnpm';
246
- else if (has('yarn.lock'))
247
- packageManager = 'yarn';
248
- else if (has('bun.lockb') || has('bun.lock'))
249
- packageManager = 'bun';
250
- else if (has('package-lock.json') || has('npm-shrinkwrap.json'))
251
- packageManager = 'npm';
252
- else if (rootPkg?.packageManagerField)
253
- packageManager = rootPkg.packageManagerField.split('@')[0] ?? null;
254
- else if (rootPkg)
255
- packageManager = 'npm';
316
+ const pms = [...new Set(nodePkgs.map((p) => p.packageManager))].sort();
317
+ if (pms.length === 1)
318
+ packageManager = pms[0];
319
+ else if (pms.length > 1)
320
+ packageManager = `mixed (${pms.join(', ')})`;
256
321
  // Python
257
322
  const py = await pythonText(root, scan);
258
323
  const hasPy = has('pyproject.toml') || has('requirements.txt') || has('Pipfile') || has('setup.py') || [...files].some((f) => f.endsWith('.py') && !isAuxPath(f));
@@ -301,7 +366,7 @@ export async function detectProject(input) {
301
366
  workspacePatterns = parseWorkspaceYaml((await safeReadText(root, 'pnpm-workspace.yaml', 64 * 1024).catch(() => null)) ?? '');
302
367
  }
303
368
  else if (rootPkg && rootPkg.workspaces.length > 0) {
304
- monoTool = packageManager === 'yarn' ? 'yarn-workspaces' : 'npm-workspaces';
369
+ monoTool = rootNode?.packageManager === 'yarn' ? 'yarn-workspaces' : 'npm-workspaces';
305
370
  workspacePatterns = rootPkg.workspaces;
306
371
  }
307
372
  else if (has('lerna.json'))
@@ -321,28 +386,19 @@ export async function detectProject(input) {
321
386
  else if (has('go.work'))
322
387
  monoTool = 'go-work';
323
388
  const packages = [];
324
- if (monoTool) {
325
- if (workspacePatterns.length === 0 && (monoTool === 'lerna' || monoTool === 'nx' || monoTool === 'turborepo')) {
326
- workspacePatterns = ['packages/*', 'apps/*', 'libs/*'];
327
- }
328
- const dirs = expandWorkspaceGlobs(workspacePatterns, files, manifest).slice(0, 100);
329
- for (const d of dirs) {
330
- if (manifest === 'package.json') {
331
- const p = await readPackageJson(root, `${d}/package.json`);
332
- packages.push({
333
- path: d,
334
- name: p?.name ?? path.posix.basename(d),
335
- ecosystem: 'node',
336
- frameworks: p ? nodeFrameworks(p).map((f) => f.name) : [],
337
- });
338
- if (p)
339
- nodeFrameworks(p).forEach(addFw);
340
- }
341
- else {
342
- packages.push({ path: d, name: path.posix.basename(d), ecosystem: 'rust', frameworks: [] });
343
- }
389
+ for (const p of nodePkgs) {
390
+ if (p.dir === '')
391
+ continue;
392
+ packages.push({ path: p.dir, name: p.pkg.name ?? path.posix.basename(p.dir), ecosystem: 'node', frameworks: nodeFrameworks(p.pkg).map((f) => f.name), packageManager: p.packageManager });
393
+ }
394
+ if (monoTool === 'cargo-workspace') {
395
+ for (const d of expandWorkspaceGlobs(workspacePatterns, files, manifest).slice(0, 100)) {
396
+ packages.push({ path: d, name: path.posix.basename(d), ecosystem: 'rust', frameworks: [] });
344
397
  }
345
398
  }
399
+ // Several packages without any workspace tooling (e.g. backend/ + frontend/ and no root package.json) is still one repository of many packages.
400
+ if (!monoTool && nodePkgs.length >= 2)
401
+ monoTool = 'multi-package';
346
402
  const testConfigs = [...files].filter((f) => TEST_CONFIG_RE.test(f) && f.split('/').length <= 4 && !isAuxPath(f)).sort().slice(0, 30);
347
403
  const ci = [
348
404
  ...[...files].filter((f) => f.startsWith('.github/workflows/')),
@@ -365,25 +421,32 @@ export async function detectProject(input) {
365
421
  .filter(has)
366
422
  .concat([...files].filter((f) => /^(k8s|kubernetes|deploy|infra|terraform)\//.test(f)).slice(0, 5))
367
423
  .sort();
368
- const aiInstructions = [...AI_FILES.filter(has), ...[...files].filter((f) => f.startsWith('.claude/') && /\.(md|json)$/.test(f)).slice(0, 20)].sort();
369
- const docs = [
370
- ...[...files].filter((f) => /^readme(\.[a-z]+)?$/i.test(f)),
371
- ...[...files].filter((f) => /^docs\/[^/]+\.(md|mdx|rst)$/i.test(f)).slice(0, 15),
372
- ...['CONTRIBUTING.md', 'ARCHITECTURE.md', 'CHANGELOG.md'].filter(has),
373
- ].sort();
424
+ // Instruction files only: CLAUDE.md, settings and each skill's SKILL.md. A skill's reference documents are tool-managed noise.
425
+ const claudeFiles = [...files].filter((f) => /^\.claude\/(?:[^/]+\.(?:md|json)|skills\/[^/]+\/SKILL\.md)$/.test(f)).slice(0, 20);
426
+ const aiInstructions = [...new Set([...AI_FILES.filter(has), ...claudeFiles])].sort();
427
+ const { docs, omitted: docsOmitted } = detectDocs(files, nodePkgs.map((p) => p.dir));
428
+ const entryPoints = discoverEntryPoints(nodePkgs, files);
374
429
  const entryHints = [];
375
430
  for (const cand of ['src/index.ts', 'src/main.ts', 'src/app.ts', 'src/server.ts', 'index.js', 'server.js', 'app.js', 'main.py', 'app/main.py', 'main.go', 'cmd', 'src/main.rs', 'manage.py', 'src/App.tsx', 'app/layout.tsx']) {
376
431
  if (has(cand) || [...files].some((f) => f.startsWith(cand + '/')))
377
432
  entryHints.push(cand);
378
433
  }
379
434
  const commands = buildContract({
380
- pkg: rootPkg,
381
- packageManager,
435
+ nodePackages: nodePkgs,
382
436
  ecosystems,
383
437
  has,
384
438
  pythonEvidence: py.evidence,
385
439
  files,
386
440
  });
441
+ const languages = languagesFrom(scan.byExtension).slice(0, 12);
442
+ if (ecosystems.size === 0 && languages.length > 0) {
443
+ warnings.push(`No ecosystem was recognised although source files were found (${languages.slice(0, 3).map((l) => l.name).join(', ')}). Package manifests may be missing or unsupported; record verification commands by hand in .devworkspace/context/commands.json.`);
444
+ }
445
+ if (ecosystems.size > 0 && !commands.some((c) => c.available)) {
446
+ warnings.push('No verification commands (tests, lint, typecheck, build) were found in the package manifests.');
447
+ }
448
+ if (docsOmitted > 0)
449
+ warnings.push(`${docsOmitted} more documentation file(s) were found than are listed (limit ${MAX_DOCS}).`);
387
450
  if (scan.truncated)
388
451
  warnings.push('Scan hit its file or depth limit; discovery is partial.');
389
452
  if (scan.sensitiveFiles.length > 0)
@@ -400,13 +463,14 @@ export async function detectProject(input) {
400
463
  skippedSymlinks: scan.skippedSymlinks,
401
464
  ignoredEntries: scan.ignoredEntries,
402
465
  },
403
- languages: languagesFrom(scan.byExtension).slice(0, 12),
466
+ languages,
404
467
  topDirs: scan.topDirs,
405
468
  ecosystems: [...ecosystems].sort(),
406
469
  packageManager,
407
470
  frameworks: [...frameworks.values()].sort((a, b) => a.name.localeCompare(b.name)),
408
471
  monorepo: { tool: monoTool, packages },
409
472
  commands,
473
+ manifests: [...nodePkgs.map((p) => p.manifest), ...['pyproject.toml', 'requirements.txt', 'Pipfile', 'go.mod', 'Cargo.toml', 'pom.xml', 'build.gradle', 'build.gradle.kts', 'composer.json', 'Gemfile'].filter(has)].sort(),
410
474
  testConfigs,
411
475
  ci,
412
476
  docker,
@@ -415,6 +479,7 @@ export async function detectProject(input) {
415
479
  docs,
416
480
  sensitiveFilesPresent: scan.sensitiveFiles.filter((f) => isSensitiveFile(f)),
417
481
  entryHints,
482
+ entryPoints,
418
483
  warnings,
419
484
  };
420
485
  }
@@ -1 +1 @@
1
- {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/discovery/detect.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { safeReadText } from '../security/files.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport type { ScanResult } from './scan.js';\nimport { buildContract } from './commands.js';\nimport type { CommandEntry } from '../config/schemas.js';\n\nexport interface Detected {\n name: string;\n category: 'framework' | 'test' | 'tool' | 'database' | 'runtime';\n evidence: string;\n}\n\nexport interface SubProject {\n path: string;\n name: string;\n ecosystem: string;\n frameworks: string[];\n}\n\nexport interface PackageInfo {\n rel: string;\n name?: string;\n scripts: Record<string, string>;\n deps: Record<string, string>;\n workspaces: string[];\n packageManagerField?: string;\n hasTypes: boolean;\n type?: string;\n}\n\nexport interface DiscoveryReport {\n schemaVersion: 1;\n project: { name: string };\n scan: {\n fileCount: number;\n dirCount: number;\n truncated: boolean;\n skippedSymlinks: number;\n ignoredEntries: number;\n };\n languages: { name: string; files: number }[];\n topDirs: { name: string; files: number }[];\n ecosystems: string[];\n packageManager: string | null;\n frameworks: Detected[];\n monorepo: { tool: string | null; packages: SubProject[] };\n commands: CommandEntry[];\n testConfigs: string[];\n ci: string[];\n docker: string[];\n deployment: string[];\n aiInstructions: string[];\n docs: string[];\n /** Names of credential-like files that exist. Their content is never read. */\n sensitiveFilesPresent: string[];\n entryHints: string[];\n warnings: string[];\n}\n\nconst EXT_LANG: Record<string, string> = {\n '.ts': 'TypeScript',\n '.tsx': 'TypeScript',\n '.mts': 'TypeScript',\n '.cts': 'TypeScript',\n '.js': 'JavaScript',\n '.jsx': 'JavaScript',\n '.mjs': 'JavaScript',\n '.cjs': 'JavaScript',\n '.py': 'Python',\n '.go': 'Go',\n '.rs': 'Rust',\n '.java': 'Java',\n '.kt': 'Kotlin',\n '.php': 'PHP',\n '.rb': 'Ruby',\n '.cs': 'C#',\n '.swift': 'Swift',\n '.c': 'C',\n '.h': 'C',\n '.cpp': 'C++',\n '.cc': 'C++',\n '.hpp': 'C++',\n '.vue': 'Vue',\n '.svelte': 'Svelte',\n '.sql': 'SQL',\n};\n\nconst NODE_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n express: { name: 'Express', category: 'framework' },\n fastify: { name: 'Fastify', category: 'framework' },\n koa: { name: 'Koa', category: 'framework' },\n hono: { name: 'Hono', category: 'framework' },\n '@nestjs/core': { name: 'NestJS', category: 'framework' },\n next: { name: 'Next.js', category: 'framework' },\n react: { name: 'React', category: 'framework' },\n vue: { name: 'Vue', category: 'framework' },\n nuxt: { name: 'Nuxt', category: 'framework' },\n svelte: { name: 'Svelte', category: 'framework' },\n '@sveltejs/kit': { name: 'SvelteKit', category: 'framework' },\n '@angular/core': { name: 'Angular', category: 'framework' },\n astro: { name: 'Astro', category: 'framework' },\n electron: { name: 'Electron', category: 'framework' },\n '@remix-run/react': { name: 'Remix', category: 'framework' },\n vite: { name: 'Vite', category: 'tool' },\n typescript: { name: 'TypeScript', category: 'tool' },\n eslint: { name: 'ESLint', category: 'tool' },\n prettier: { name: 'Prettier', category: 'tool' },\n tailwindcss: { name: 'Tailwind CSS', category: 'tool' },\n webpack: { name: 'webpack', category: 'tool' },\n '@biomejs/biome': { name: 'Biome', category: 'tool' },\n jest: { name: 'Jest', category: 'test' },\n vitest: { name: 'Vitest', category: 'test' },\n mocha: { name: 'Mocha', category: 'test' },\n '@playwright/test': { name: 'Playwright', category: 'test' },\n cypress: { name: 'Cypress', category: 'test' },\n prisma: { name: 'Prisma', category: 'database' },\n '@prisma/client': { name: 'Prisma', category: 'database' },\n typeorm: { name: 'TypeORM', category: 'database' },\n mongoose: { name: 'Mongoose', category: 'database' },\n sequelize: { name: 'Sequelize', category: 'database' },\n 'drizzle-orm': { name: 'Drizzle', category: 'database' },\n knex: { name: 'Knex', category: 'database' },\n pg: { name: 'PostgreSQL client', category: 'database' },\n redis: { name: 'Redis client', category: 'database' },\n ioredis: { name: 'Redis client', category: 'database' },\n};\n\nconst PY_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n fastapi: { name: 'FastAPI', category: 'framework' },\n django: { name: 'Django', category: 'framework' },\n flask: { name: 'Flask', category: 'framework' },\n starlette: { name: 'Starlette', category: 'framework' },\n celery: { name: 'Celery', category: 'framework' },\n pydantic: { name: 'Pydantic', category: 'tool' },\n sqlalchemy: { name: 'SQLAlchemy', category: 'database' },\n alembic: { name: 'Alembic', category: 'database' },\n pytest: { name: 'pytest', category: 'test' },\n ruff: { name: 'Ruff', category: 'tool' },\n mypy: { name: 'mypy', category: 'tool' },\n black: { name: 'Black', category: 'tool' },\n};\n\nconst TEST_CONFIG_RE =\n /(^|\\/)(jest\\.config\\.[cm]?[jt]s|jest\\.config\\.json|vitest\\.config\\.[cm]?[jt]s|vitest\\.workspace\\.[cm]?[jt]s|playwright\\.config\\.[cm]?[jt]s|cypress\\.config\\.[cm]?[jt]s|\\.mocharc\\.[a-z]+|pytest\\.ini|tox\\.ini|conftest\\.py|phpunit\\.xml(\\.dist)?|karma\\.conf\\.[cm]?js)$/;\n\nconst AI_FILES = [\n 'CLAUDE.md',\n 'CLAUDE.local.md',\n '.claude/CLAUDE.md',\n 'AGENTS.md',\n 'GEMINI.md',\n '.cursorrules',\n '.github/copilot-instructions.md',\n '.windsurfrules',\n];\n\n/** Directories that hold samples or test data rather than the project's own code; they must not define its stack. */\nconst AUX_DIRS = new Set(['fixtures', 'fixture', '__fixtures__', 'examples', 'example', 'samples', 'sample', 'testdata', 'test-data', 'demo', 'demos', 'docs', 'doc', 'third_party', 'thirdparty']);\n\nexport function isAuxPath(rel: string): boolean {\n return rel.split('/').slice(0, -1).some((s) => AUX_DIRS.has(s.toLowerCase()));\n}\n\nfunction parseJsonLoose(text: string | null): Record<string, unknown> | null {\n if (!text) return null;\n try {\n const v = JSON.parse(text);\n return typeof v === 'object' && v !== null && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction strMap(v: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (typeof v === 'object' && v !== null) {\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) if (typeof val === 'string') out[k] = val;\n }\n return out;\n}\n\nexport async function readPackageJson(root: string, rel: string): Promise<PackageInfo | null> {\n let text: string | null;\n try {\n text = await safeReadText(root, rel, 1024 * 1024);\n } catch {\n return null;\n }\n const j = parseJsonLoose(text);\n if (!j) return null;\n const ws = j.workspaces;\n const workspaces = Array.isArray(ws)\n ? ws.filter((x): x is string => typeof x === 'string')\n : typeof ws === 'object' && ws !== null && Array.isArray((ws as { packages?: unknown }).packages)\n ? ((ws as { packages: unknown[] }).packages.filter((x) => typeof x === 'string') as string[])\n : [];\n const deps = { ...strMap(j.dependencies), ...strMap(j.devDependencies), ...strMap(j.peerDependencies) };\n return {\n rel,\n name: typeof j.name === 'string' ? j.name : undefined,\n scripts: strMap(j.scripts),\n deps,\n workspaces,\n packageManagerField: typeof j.packageManager === 'string' ? j.packageManager : undefined,\n hasTypes: 'typescript' in deps,\n type: typeof j.type === 'string' ? j.type : undefined,\n };\n}\n\nfunction nodeFrameworks(pkg: PackageInfo): Detected[] {\n const out = new Map<string, Detected>();\n for (const dep of Object.keys(pkg.deps)) {\n const hit = NODE_DEP_MAP[dep];\n if (hit && !out.has(hit.name)) out.set(hit.name, { ...hit, evidence: pkg.rel });\n }\n return [...out.values()];\n}\n\nasync function pythonText(root: string, scan: ScanResult): Promise<{ text: string; evidence: Record<string, string> }> {\n const names = [...scan.files].filter((f) => {\n const b = path.posix.basename(f);\n const depth = f.split('/').length;\n return depth <= 3 && !isAuxPath(f) && (b === 'pyproject.toml' || /^requirements.*\\.txt$/.test(b) || b === 'Pipfile' || b === 'setup.py' || b === 'setup.cfg');\n });\n let text = '';\n const evidence: Record<string, string> = {};\n for (const n of names.slice(0, 12)) {\n const t = await safeReadText(root, n, 256 * 1024).catch(() => null);\n if (t) {\n text += `\\n${t.toLowerCase()}`;\n for (const key of Object.keys(PY_DEP_MAP)) {\n if (!evidence[key] && new RegExp(`(^|[\\\\s\"'\\\\[,=<>~!-])${key}(?![a-z0-9_])`, 'm').test(t.toLowerCase())) evidence[key] = n;\n }\n }\n }\n return { text, evidence };\n}\n\nfunction parseWorkspaceYaml(text: string): string[] {\n const out: string[] = [];\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*-\\s*['\"]?([^'\"#]+?)['\"]?\\s*(?:#.*)?$/.exec(line);\n if (m && m[1] && !m[1].startsWith('!')) out.push(m[1].trim());\n }\n return out;\n}\n\n/** Expand simple workspace globs (\"packages/*\", \"apps/**\" treated as one level, or a literal directory). */\nexport function expandWorkspaceGlobs(patterns: string[], files: Set<string>, manifest: string): string[] {\n const dirs = new Set<string>();\n for (const f of files) {\n if (path.posix.basename(f) === manifest && f.includes('/')) dirs.add(path.posix.dirname(f));\n }\n const out = new Set<string>();\n for (const pat of patterns) {\n const clean = pat.replace(/^\\.\\//, '').replace(/\\/$/, '');\n if (!clean.includes('*')) {\n if (dirs.has(clean)) out.add(clean);\n continue;\n }\n const prefix = clean.slice(0, clean.indexOf('*')).replace(/\\/$/, '');\n const deep = clean.includes('**');\n for (const d of dirs) {\n if (!d.startsWith(prefix + '/')) continue;\n const rest = d.slice(prefix.length + 1);\n if (deep || !rest.includes('/')) out.add(d);\n }\n }\n return [...out].sort();\n}\n\nfunction languagesFrom(byExt: Record<string, number>): { name: string; files: number }[] {\n const acc = new Map<string, number>();\n for (const [ext, n] of Object.entries(byExt)) {\n const lang = EXT_LANG[ext];\n if (lang) acc.set(lang, (acc.get(lang) ?? 0) + n);\n }\n return [...acc.entries()].map(([name, files]) => ({ name, files })).sort((a, b) => b.files - a.files || a.name.localeCompare(b.name));\n}\n\nexport interface DetectInput {\n root: string;\n projectName: string;\n scan: ScanResult;\n}\n\nexport async function detectProject(input: DetectInput): Promise<DiscoveryReport> {\n const { root, scan } = input;\n const files = scan.files;\n const has = (rel: string): boolean => files.has(rel);\n const warnings: string[] = [];\n const ecosystems = new Set<string>();\n const frameworks = new Map<string, Detected>();\n const addFw = (d: Detected): void => {\n if (!frameworks.has(d.name)) frameworks.set(d.name, d);\n };\n\n // Node / JS\n const rootPkg = has('package.json') ? await readPackageJson(root, 'package.json') : null;\n if (has('package.json') && !rootPkg) warnings.push('package.json exists but could not be parsed.');\n if (rootPkg) {\n ecosystems.add('node');\n nodeFrameworks(rootPkg).forEach(addFw);\n }\n let packageManager: string | null = null;\n if (has('pnpm-lock.yaml')) packageManager = 'pnpm';\n else if (has('yarn.lock')) packageManager = 'yarn';\n else if (has('bun.lockb') || has('bun.lock')) packageManager = 'bun';\n else if (has('package-lock.json') || has('npm-shrinkwrap.json')) packageManager = 'npm';\n else if (rootPkg?.packageManagerField) packageManager = rootPkg.packageManagerField.split('@')[0] ?? null;\n else if (rootPkg) packageManager = 'npm';\n\n // Python\n const py = await pythonText(root, scan);\n const hasPy = has('pyproject.toml') || has('requirements.txt') || has('Pipfile') || has('setup.py') || [...files].some((f) => f.endsWith('.py') && !isAuxPath(f));\n if (hasPy) {\n ecosystems.add('python');\n for (const [k, ev] of Object.entries(py.evidence)) {\n const m = PY_DEP_MAP[k];\n if (m) addFw({ ...m, evidence: ev });\n }\n if (!packageManager) {\n if (has('poetry.lock') || py.text.includes('[tool.poetry]')) packageManager = 'poetry';\n else if (has('uv.lock')) packageManager = 'uv';\n else if (has('Pipfile')) packageManager = 'pipenv';\n else if (has('requirements.txt') || has('pyproject.toml')) packageManager = 'pip';\n }\n }\n\n const simple: [string, string, string][] = [\n ['go.mod', 'go', 'go'],\n ['Cargo.toml', 'rust', 'cargo'],\n ['pom.xml', 'java', 'maven'],\n ['build.gradle', 'java', 'gradle'],\n ['build.gradle.kts', 'java', 'gradle'],\n ['composer.json', 'php', 'composer'],\n ['Gemfile', 'ruby', 'bundler'],\n ];\n for (const [file, eco, pm] of simple) {\n if (has(file)) {\n ecosystems.add(eco);\n if (!packageManager) packageManager = pm;\n }\n }\n if ([...files].some((f) => /\\.csproj$/.test(f) && f.split('/').length <= 3)) ecosystems.add('dotnet');\n\n // Monorepo\n let monoTool: string | null = null;\n let workspacePatterns: string[] = [];\n let manifest = 'package.json';\n if (has('pnpm-workspace.yaml')) {\n monoTool = 'pnpm-workspaces';\n workspacePatterns = parseWorkspaceYaml((await safeReadText(root, 'pnpm-workspace.yaml', 64 * 1024).catch(() => null)) ?? '');\n } else if (rootPkg && rootPkg.workspaces.length > 0) {\n monoTool = packageManager === 'yarn' ? 'yarn-workspaces' : 'npm-workspaces';\n workspacePatterns = rootPkg.workspaces;\n } else if (has('lerna.json')) monoTool = 'lerna';\n else if (has('nx.json')) monoTool = 'nx';\n else if (has('turbo.json')) monoTool = 'turborepo';\n else if (has('Cargo.toml')) {\n const cargo = (await safeReadText(root, 'Cargo.toml', 64 * 1024).catch(() => null)) ?? '';\n if (/^\\[workspace\\]/m.test(cargo)) {\n monoTool = 'cargo-workspace';\n manifest = 'Cargo.toml';\n workspacePatterns = [...cargo.matchAll(/\"([^\"]+)\"/g)].map((m) => m[1]!).filter((s) => !s.includes(' '));\n }\n } else if (has('go.work')) monoTool = 'go-work';\n\n const packages: SubProject[] = [];\n if (monoTool) {\n if (workspacePatterns.length === 0 && (monoTool === 'lerna' || monoTool === 'nx' || monoTool === 'turborepo')) {\n workspacePatterns = ['packages/*', 'apps/*', 'libs/*'];\n }\n const dirs = expandWorkspaceGlobs(workspacePatterns, files, manifest).slice(0, 100);\n for (const d of dirs) {\n if (manifest === 'package.json') {\n const p = await readPackageJson(root, `${d}/package.json`);\n packages.push({\n path: d,\n name: p?.name ?? path.posix.basename(d),\n ecosystem: 'node',\n frameworks: p ? nodeFrameworks(p).map((f) => f.name) : [],\n });\n if (p) nodeFrameworks(p).forEach(addFw);\n } else {\n packages.push({ path: d, name: path.posix.basename(d), ecosystem: 'rust', frameworks: [] });\n }\n }\n }\n\n const testConfigs = [...files].filter((f) => TEST_CONFIG_RE.test(f) && f.split('/').length <= 4 && !isAuxPath(f)).sort().slice(0, 30);\n const ci = [\n ...[...files].filter((f) => f.startsWith('.github/workflows/')),\n ...['.gitlab-ci.yml', 'azure-pipelines.yml', 'Jenkinsfile', '.travis.yml', 'bitbucket-pipelines.yml', '.circleci/config.yml'].filter(has),\n ].sort();\n const docker = [...files].filter((f) => !isAuxPath(f) && /(^|\\/)(Dockerfile(\\..+)?|docker-compose[^/]*\\.ya?ml|compose\\.ya?ml)$/.test(f) && f.split('/').length <= 3).sort();\n const deployment = [\n 'vercel.json',\n 'netlify.toml',\n 'fly.toml',\n 'render.yaml',\n 'Procfile',\n 'app.yaml',\n 'serverless.yml',\n 'wrangler.toml',\n 'railway.json',\n 'firebase.json',\n 'Chart.yaml',\n ]\n .filter(has)\n .concat([...files].filter((f) => /^(k8s|kubernetes|deploy|infra|terraform)\\//.test(f)).slice(0, 5))\n .sort();\n const aiInstructions = [...AI_FILES.filter(has), ...[...files].filter((f) => f.startsWith('.claude/') && /\\.(md|json)$/.test(f)).slice(0, 20)].sort();\n const docs = [\n ...[...files].filter((f) => /^readme(\\.[a-z]+)?$/i.test(f)),\n ...[...files].filter((f) => /^docs\\/[^/]+\\.(md|mdx|rst)$/i.test(f)).slice(0, 15),\n ...['CONTRIBUTING.md', 'ARCHITECTURE.md', 'CHANGELOG.md'].filter(has),\n ].sort();\n\n const entryHints: string[] = [];\n for (const cand of ['src/index.ts', 'src/main.ts', 'src/app.ts', 'src/server.ts', 'index.js', 'server.js', 'app.js', 'main.py', 'app/main.py', 'main.go', 'cmd', 'src/main.rs', 'manage.py', 'src/App.tsx', 'app/layout.tsx']) {\n if (has(cand) || [...files].some((f) => f.startsWith(cand + '/'))) entryHints.push(cand);\n }\n\n const commands = buildContract({\n pkg: rootPkg,\n packageManager,\n ecosystems,\n has,\n pythonEvidence: py.evidence,\n files,\n });\n\n if (scan.truncated) warnings.push('Scan hit its file or depth limit; discovery is partial.');\n if (scan.sensitiveFiles.length > 0) warnings.push('Credential-like files exist; their contents were not read.');\n if (!has('README.md') && !docs.some((d) => /^readme/i.test(d))) warnings.push('No README found.');\n\n return {\n schemaVersion: 1,\n project: { name: rootPkg?.name ?? input.projectName },\n scan: {\n fileCount: scan.fileCount,\n dirCount: scan.dirCount,\n truncated: scan.truncated,\n skippedSymlinks: scan.skippedSymlinks,\n ignoredEntries: scan.ignoredEntries,\n },\n languages: languagesFrom(scan.byExtension).slice(0, 12),\n topDirs: scan.topDirs,\n ecosystems: [...ecosystems].sort(),\n packageManager,\n frameworks: [...frameworks.values()].sort((a, b) => a.name.localeCompare(b.name)),\n monorepo: { tool: monoTool, packages },\n commands,\n testConfigs,\n ci,\n docker,\n deployment,\n aiInstructions,\n docs,\n sensitiveFilesPresent: scan.sensitiveFiles.filter((f) => isSensitiveFile(f)),\n entryHints,\n warnings,\n };\n}\n"]}
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/discovery/detect.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { safeReadText } from '../security/files.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport type { ScanResult } from './scan.js';\nimport { buildContract, type NodePackageInput } from './commands.js';\nimport type { CommandEntry } from '../config/schemas.js';\nimport { detectDocs, MAX_DOCS } from './docs.js';\nimport { discoverEntryPoints, type EntryPoint } from './entrypoints.js';\n\nexport interface Detected {\n name: string;\n category: 'framework' | 'test' | 'tool' | 'database' | 'runtime';\n evidence: string;\n}\n\nexport interface SubProject {\n path: string;\n name: string;\n ecosystem: string;\n frameworks: string[];\n packageManager?: string;\n}\n\nexport interface PackageInfo {\n rel: string;\n name?: string;\n scripts: Record<string, string>;\n deps: Record<string, string>;\n workspaces: string[];\n packageManagerField?: string;\n hasTypes: boolean;\n type?: string;\n /** `main` field and `bin` targets, used as evidence for entry points. */\n main?: string;\n bin?: string[];\n}\n\nexport interface DiscoveryReport {\n schemaVersion: 1;\n project: { name: string };\n scan: {\n fileCount: number;\n dirCount: number;\n truncated: boolean;\n skippedSymlinks: number;\n ignoredEntries: number;\n };\n languages: { name: string; files: number }[];\n topDirs: { name: string; files: number }[];\n ecosystems: string[];\n packageManager: string | null;\n frameworks: Detected[];\n monorepo: { tool: string | null; packages: SubProject[] };\n commands: CommandEntry[];\n /** Recognised package manifests (project-relative). Used as evidence for derived facts. */\n manifests: string[];\n testConfigs: string[];\n ci: string[];\n docker: string[];\n deployment: string[];\n aiInstructions: string[];\n docs: string[];\n /** Names of credential-like files that exist. Their content is never read. */\n sensitiveFilesPresent: string[];\n entryHints: string[];\n /** Entry points a package itself declares (start-like scripts, `main`, `bin`), with the evidence for each. */\n entryPoints: EntryPoint[];\n warnings: string[];\n}\n\nconst EXT_LANG: Record<string, string> = {\n '.ts': 'TypeScript',\n '.tsx': 'TypeScript',\n '.mts': 'TypeScript',\n '.cts': 'TypeScript',\n '.js': 'JavaScript',\n '.jsx': 'JavaScript',\n '.mjs': 'JavaScript',\n '.cjs': 'JavaScript',\n '.py': 'Python',\n '.go': 'Go',\n '.rs': 'Rust',\n '.java': 'Java',\n '.kt': 'Kotlin',\n '.php': 'PHP',\n '.rb': 'Ruby',\n '.cs': 'C#',\n '.swift': 'Swift',\n '.c': 'C',\n '.h': 'C',\n '.cpp': 'C++',\n '.cc': 'C++',\n '.hpp': 'C++',\n '.vue': 'Vue',\n '.svelte': 'Svelte',\n '.sql': 'SQL',\n};\n\nconst NODE_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n express: { name: 'Express', category: 'framework' },\n fastify: { name: 'Fastify', category: 'framework' },\n koa: { name: 'Koa', category: 'framework' },\n hono: { name: 'Hono', category: 'framework' },\n '@nestjs/core': { name: 'NestJS', category: 'framework' },\n next: { name: 'Next.js', category: 'framework' },\n react: { name: 'React', category: 'framework' },\n vue: { name: 'Vue', category: 'framework' },\n nuxt: { name: 'Nuxt', category: 'framework' },\n svelte: { name: 'Svelte', category: 'framework' },\n '@sveltejs/kit': { name: 'SvelteKit', category: 'framework' },\n '@angular/core': { name: 'Angular', category: 'framework' },\n astro: { name: 'Astro', category: 'framework' },\n electron: { name: 'Electron', category: 'framework' },\n '@remix-run/react': { name: 'Remix', category: 'framework' },\n vite: { name: 'Vite', category: 'tool' },\n typescript: { name: 'TypeScript', category: 'tool' },\n eslint: { name: 'ESLint', category: 'tool' },\n prettier: { name: 'Prettier', category: 'tool' },\n tailwindcss: { name: 'Tailwind CSS', category: 'tool' },\n webpack: { name: 'webpack', category: 'tool' },\n '@biomejs/biome': { name: 'Biome', category: 'tool' },\n jest: { name: 'Jest', category: 'test' },\n vitest: { name: 'Vitest', category: 'test' },\n mocha: { name: 'Mocha', category: 'test' },\n '@playwright/test': { name: 'Playwright', category: 'test' },\n cypress: { name: 'Cypress', category: 'test' },\n prisma: { name: 'Prisma', category: 'database' },\n '@prisma/client': { name: 'Prisma', category: 'database' },\n typeorm: { name: 'TypeORM', category: 'database' },\n mongoose: { name: 'Mongoose', category: 'database' },\n sequelize: { name: 'Sequelize', category: 'database' },\n 'drizzle-orm': { name: 'Drizzle', category: 'database' },\n knex: { name: 'Knex', category: 'database' },\n pg: { name: 'PostgreSQL client', category: 'database' },\n redis: { name: 'Redis client', category: 'database' },\n ioredis: { name: 'Redis client', category: 'database' },\n};\n\nconst PY_DEP_MAP: Record<string, { name: string; category: Detected['category'] }> = {\n fastapi: { name: 'FastAPI', category: 'framework' },\n django: { name: 'Django', category: 'framework' },\n flask: { name: 'Flask', category: 'framework' },\n starlette: { name: 'Starlette', category: 'framework' },\n celery: { name: 'Celery', category: 'framework' },\n pydantic: { name: 'Pydantic', category: 'tool' },\n sqlalchemy: { name: 'SQLAlchemy', category: 'database' },\n alembic: { name: 'Alembic', category: 'database' },\n pytest: { name: 'pytest', category: 'test' },\n ruff: { name: 'Ruff', category: 'tool' },\n mypy: { name: 'mypy', category: 'tool' },\n black: { name: 'Black', category: 'tool' },\n};\n\nconst TEST_CONFIG_RE =\n /(^|\\/)(jest\\.config\\.[cm]?[jt]s|jest\\.config\\.json|vitest\\.config\\.[cm]?[jt]s|vitest\\.workspace\\.[cm]?[jt]s|playwright\\.config\\.[cm]?[jt]s|cypress\\.config\\.[cm]?[jt]s|\\.mocharc\\.[a-z]+|pytest\\.ini|tox\\.ini|conftest\\.py|phpunit\\.xml(\\.dist)?|karma\\.conf\\.[cm]?js)$/;\n\nconst AI_FILES = [\n 'CLAUDE.md',\n 'CLAUDE.local.md',\n '.claude/CLAUDE.md',\n 'AGENTS.md',\n 'GEMINI.md',\n '.cursorrules',\n '.github/copilot-instructions.md',\n '.windsurfrules',\n];\n\n/** Directories that hold samples or test data rather than the project's own code; they must not define its stack. */\nconst AUX_DIRS = new Set(['fixtures', 'fixture', '__fixtures__', 'examples', 'example', 'samples', 'sample', 'testdata', 'test-data', 'demo', 'demos', 'docs', 'doc', 'third_party', 'thirdparty']);\n\nexport function isAuxPath(rel: string): boolean {\n return rel.split('/').slice(0, -1).some((s) => AUX_DIRS.has(s.toLowerCase()));\n}\n\nfunction parseJsonLoose(text: string | null): Record<string, unknown> | null {\n if (!text) return null;\n try {\n const v = JSON.parse(text);\n return typeof v === 'object' && v !== null && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction strMap(v: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (typeof v === 'object' && v !== null) {\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) if (typeof val === 'string') out[k] = val;\n }\n return out;\n}\n\nexport async function readPackageJson(root: string, rel: string): Promise<PackageInfo | null> {\n let text: string | null;\n try {\n text = await safeReadText(root, rel, 1024 * 1024);\n } catch {\n return null;\n }\n const j = parseJsonLoose(text);\n if (!j) return null;\n const ws = j.workspaces;\n const workspaces = Array.isArray(ws)\n ? ws.filter((x): x is string => typeof x === 'string')\n : typeof ws === 'object' && ws !== null && Array.isArray((ws as { packages?: unknown }).packages)\n ? ((ws as { packages: unknown[] }).packages.filter((x) => typeof x === 'string') as string[])\n : [];\n const deps = { ...strMap(j.dependencies), ...strMap(j.devDependencies), ...strMap(j.peerDependencies) };\n return {\n rel,\n name: typeof j.name === 'string' ? j.name : undefined,\n scripts: strMap(j.scripts),\n deps,\n workspaces,\n packageManagerField: typeof j.packageManager === 'string' ? j.packageManager : undefined,\n hasTypes: 'typescript' in deps,\n type: typeof j.type === 'string' ? j.type : undefined,\n main: typeof j.main === 'string' ? j.main : undefined,\n bin: typeof j.bin === 'string' ? [j.bin] : Object.values(strMap(j.bin)),\n };\n}\n\nfunction nodeFrameworks(pkg: PackageInfo): Detected[] {\n const out = new Map<string, Detected>();\n for (const dep of Object.keys(pkg.deps)) {\n const hit = NODE_DEP_MAP[dep];\n if (hit && !out.has(hit.name)) out.set(hit.name, { ...hit, evidence: pkg.rel });\n }\n return [...out.values()];\n}\n\nasync function pythonText(root: string, scan: ScanResult): Promise<{ text: string; evidence: Record<string, string> }> {\n const names = [...scan.files].filter((f) => {\n const b = path.posix.basename(f);\n const depth = f.split('/').length;\n return depth <= 3 && !isAuxPath(f) && (b === 'pyproject.toml' || /^requirements.*\\.txt$/.test(b) || b === 'Pipfile' || b === 'setup.py' || b === 'setup.cfg');\n });\n let text = '';\n const evidence: Record<string, string> = {};\n for (const n of names.slice(0, 12)) {\n const t = await safeReadText(root, n, 256 * 1024).catch(() => null);\n if (t) {\n text += `\\n${t.toLowerCase()}`;\n for (const key of Object.keys(PY_DEP_MAP)) {\n if (!evidence[key] && new RegExp(`(^|[\\\\s\"'\\\\[,=<>~!-])${key}(?![a-z0-9_])`, 'm').test(t.toLowerCase())) evidence[key] = n;\n }\n }\n }\n return { text, evidence };\n}\n\nfunction parseWorkspaceYaml(text: string): string[] {\n const out: string[] = [];\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*-\\s*['\"]?([^'\"#]+?)['\"]?\\s*(?:#.*)?$/.exec(line);\n if (m && m[1] && !m[1].startsWith('!')) out.push(m[1].trim());\n }\n return out;\n}\n\n/** Expand simple workspace globs (\"packages/*\", \"apps/**\" treated as one level, or a literal directory). */\nexport function expandWorkspaceGlobs(patterns: string[], files: Set<string>, manifest: string): string[] {\n const dirs = new Set<string>();\n for (const f of files) {\n if (path.posix.basename(f) === manifest && f.includes('/')) dirs.add(path.posix.dirname(f));\n }\n const out = new Set<string>();\n for (const pat of patterns) {\n const clean = pat.replace(/^\\.\\//, '').replace(/\\/$/, '');\n if (!clean.includes('*')) {\n if (dirs.has(clean)) out.add(clean);\n continue;\n }\n const prefix = clean.slice(0, clean.indexOf('*')).replace(/\\/$/, '');\n const deep = clean.includes('**');\n for (const d of dirs) {\n if (!d.startsWith(prefix + '/')) continue;\n const rest = d.slice(prefix.length + 1);\n if (deep || !rest.includes('/')) out.add(d);\n }\n }\n return [...out].sort();\n}\n\nfunction languagesFrom(byExt: Record<string, number>): { name: string; files: number }[] {\n const acc = new Map<string, number>();\n for (const [ext, n] of Object.entries(byExt)) {\n const lang = EXT_LANG[ext];\n if (lang) acc.set(lang, (acc.get(lang) ?? 0) + n);\n }\n return [...acc.entries()].map(([name, files]) => ({ name, files })).sort((a, b) => b.files - a.files || a.name.localeCompare(b.name));\n}\n\nexport interface DetectInput {\n root: string;\n projectName: string;\n scan: ScanResult;\n}\n\nconst LOCKFILES: [string, string][] = [\n ['pnpm-lock.yaml', 'pnpm'],\n ['yarn.lock', 'yarn'],\n ['bun.lockb', 'bun'],\n ['bun.lock', 'bun'],\n ['package-lock.json', 'npm'],\n ['npm-shrinkwrap.json', 'npm'],\n];\n\nconst MAX_NODE_PACKAGES = 200;\nconst MAX_MANIFEST_DEPTH = 5;\n\n/** A package.json that only sets {\"type\":\"module\"} (a marker file) is not a package. */\nfunction isRealManifest(p: PackageInfo): boolean {\n return !!p.name || Object.keys(p.scripts).length > 0 || Object.keys(p.deps).length > 0 || p.workspaces.length > 0;\n}\n\nfunction lockfilePm(files: Set<string>, dir: string): string | null {\n for (const [lock, pm] of LOCKFILES) if (files.has(dir ? `${dir}/${lock}` : lock)) return pm;\n return null;\n}\n\nexport interface FoundNodePackage extends NodePackageInput {\n manifest: string;\n /** Where the package manager came from, for transparency in discovery.json consumers. */\n pmSource: 'lockfile' | 'packageManager field' | 'inherited from root' | 'default';\n}\n\n/**\n * Find every Node.js package, not just the root one. Each package gets its own package manager from its own lockfile\n * (falling back to the packageManager field, then the root lockfile, then npm). No script is ever executed.\n */\nexport async function discoverNodePackages(root: string, files: Set<string>): Promise<{ packages: FoundNodePackage[]; unparsable: string[] }> {\n const manifests = [...files]\n .filter((f) => path.posix.basename(f) === 'package.json' && !isAuxPath(f) && f.split('/').length <= MAX_MANIFEST_DEPTH)\n .sort((a, b) => a.split('/').length - b.split('/').length || a.localeCompare(b))\n .slice(0, MAX_NODE_PACKAGES);\n const rootLockPm = lockfilePm(files, '');\n const packages: FoundNodePackage[] = [];\n const unparsable: string[] = [];\n for (const manifest of manifests) {\n const pkg = await readPackageJson(root, manifest);\n if (!pkg) {\n unparsable.push(manifest);\n continue;\n }\n if (!isRealManifest(pkg)) continue;\n const dir = path.posix.dirname(manifest) === '.' ? '' : path.posix.dirname(manifest);\n const own = lockfilePm(files, dir);\n const field = pkg.packageManagerField?.split('@')[0] ?? null;\n let packageManager: string;\n let pmSource: FoundNodePackage['pmSource'];\n if (own) {\n packageManager = own;\n pmSource = 'lockfile';\n } else if (field) {\n packageManager = field;\n pmSource = 'packageManager field';\n } else if (rootLockPm && dir !== '') {\n packageManager = rootLockPm;\n pmSource = 'inherited from root';\n } else {\n packageManager = 'npm';\n pmSource = 'default';\n }\n packages.push({ dir, pkg, packageManager, hasTsconfig: files.has(dir ? `${dir}/tsconfig.json` : 'tsconfig.json'), manifest, pmSource });\n }\n return { packages, unparsable };\n}\n\nexport async function detectProject(input: DetectInput): Promise<DiscoveryReport> {\n const { root, scan } = input;\n const files = scan.files;\n const has = (rel: string): boolean => files.has(rel);\n const warnings: string[] = [];\n const ecosystems = new Set<string>();\n const frameworks = new Map<string, Detected>();\n const addFw = (d: Detected): void => {\n if (!frameworks.has(d.name)) frameworks.set(d.name, d);\n };\n\n // Node / JS: every package.json, not only the one at the root\n const { packages: nodePkgs, unparsable } = await discoverNodePackages(root, files);\n for (const m of unparsable.slice(0, 5)) warnings.push(`${m} exists but could not be parsed.`);\n const rootNode = nodePkgs.find((p) => p.dir === '');\n const rootPkg = rootNode?.pkg ?? null;\n if (nodePkgs.length > 0) {\n ecosystems.add('node');\n for (const p of nodePkgs) nodeFrameworks(p.pkg).forEach(addFw);\n }\n let packageManager: string | null = null;\n const pms = [...new Set(nodePkgs.map((p) => p.packageManager))].sort();\n if (pms.length === 1) packageManager = pms[0]!;\n else if (pms.length > 1) packageManager = `mixed (${pms.join(', ')})`;\n\n // Python\n const py = await pythonText(root, scan);\n const hasPy = has('pyproject.toml') || has('requirements.txt') || has('Pipfile') || has('setup.py') || [...files].some((f) => f.endsWith('.py') && !isAuxPath(f));\n if (hasPy) {\n ecosystems.add('python');\n for (const [k, ev] of Object.entries(py.evidence)) {\n const m = PY_DEP_MAP[k];\n if (m) addFw({ ...m, evidence: ev });\n }\n if (!packageManager) {\n if (has('poetry.lock') || py.text.includes('[tool.poetry]')) packageManager = 'poetry';\n else if (has('uv.lock')) packageManager = 'uv';\n else if (has('Pipfile')) packageManager = 'pipenv';\n else if (has('requirements.txt') || has('pyproject.toml')) packageManager = 'pip';\n }\n }\n\n const simple: [string, string, string][] = [\n ['go.mod', 'go', 'go'],\n ['Cargo.toml', 'rust', 'cargo'],\n ['pom.xml', 'java', 'maven'],\n ['build.gradle', 'java', 'gradle'],\n ['build.gradle.kts', 'java', 'gradle'],\n ['composer.json', 'php', 'composer'],\n ['Gemfile', 'ruby', 'bundler'],\n ];\n for (const [file, eco, pm] of simple) {\n if (has(file)) {\n ecosystems.add(eco);\n if (!packageManager) packageManager = pm;\n }\n }\n if ([...files].some((f) => /\\.csproj$/.test(f) && f.split('/').length <= 3)) ecosystems.add('dotnet');\n\n // Monorepo\n let monoTool: string | null = null;\n let workspacePatterns: string[] = [];\n let manifest = 'package.json';\n if (has('pnpm-workspace.yaml')) {\n monoTool = 'pnpm-workspaces';\n workspacePatterns = parseWorkspaceYaml((await safeReadText(root, 'pnpm-workspace.yaml', 64 * 1024).catch(() => null)) ?? '');\n } else if (rootPkg && rootPkg.workspaces.length > 0) {\n monoTool = rootNode?.packageManager === 'yarn' ? 'yarn-workspaces' : 'npm-workspaces';\n workspacePatterns = rootPkg.workspaces;\n } else if (has('lerna.json')) monoTool = 'lerna';\n else if (has('nx.json')) monoTool = 'nx';\n else if (has('turbo.json')) monoTool = 'turborepo';\n else if (has('Cargo.toml')) {\n const cargo = (await safeReadText(root, 'Cargo.toml', 64 * 1024).catch(() => null)) ?? '';\n if (/^\\[workspace\\]/m.test(cargo)) {\n monoTool = 'cargo-workspace';\n manifest = 'Cargo.toml';\n workspacePatterns = [...cargo.matchAll(/\"([^\"]+)\"/g)].map((m) => m[1]!).filter((s) => !s.includes(' '));\n }\n } else if (has('go.work')) monoTool = 'go-work';\n\n const packages: SubProject[] = [];\n for (const p of nodePkgs) {\n if (p.dir === '') continue;\n packages.push({ path: p.dir, name: p.pkg.name ?? path.posix.basename(p.dir), ecosystem: 'node', frameworks: nodeFrameworks(p.pkg).map((f) => f.name), packageManager: p.packageManager });\n }\n if (monoTool === 'cargo-workspace') {\n for (const d of expandWorkspaceGlobs(workspacePatterns, files, manifest).slice(0, 100)) {\n packages.push({ path: d, name: path.posix.basename(d), ecosystem: 'rust', frameworks: [] });\n }\n }\n // Several packages without any workspace tooling (e.g. backend/ + frontend/ and no root package.json) is still one repository of many packages.\n if (!monoTool && nodePkgs.length >= 2) monoTool = 'multi-package';\n\n const testConfigs = [...files].filter((f) => TEST_CONFIG_RE.test(f) && f.split('/').length <= 4 && !isAuxPath(f)).sort().slice(0, 30);\n const ci = [\n ...[...files].filter((f) => f.startsWith('.github/workflows/')),\n ...['.gitlab-ci.yml', 'azure-pipelines.yml', 'Jenkinsfile', '.travis.yml', 'bitbucket-pipelines.yml', '.circleci/config.yml'].filter(has),\n ].sort();\n const docker = [...files].filter((f) => !isAuxPath(f) && /(^|\\/)(Dockerfile(\\..+)?|docker-compose[^/]*\\.ya?ml|compose\\.ya?ml)$/.test(f) && f.split('/').length <= 3).sort();\n const deployment = [\n 'vercel.json',\n 'netlify.toml',\n 'fly.toml',\n 'render.yaml',\n 'Procfile',\n 'app.yaml',\n 'serverless.yml',\n 'wrangler.toml',\n 'railway.json',\n 'firebase.json',\n 'Chart.yaml',\n ]\n .filter(has)\n .concat([...files].filter((f) => /^(k8s|kubernetes|deploy|infra|terraform)\\//.test(f)).slice(0, 5))\n .sort();\n // Instruction files only: CLAUDE.md, settings and each skill's SKILL.md. A skill's reference documents are tool-managed noise.\n const claudeFiles = [...files].filter((f) => /^\\.claude\\/(?:[^/]+\\.(?:md|json)|skills\\/[^/]+\\/SKILL\\.md)$/.test(f)).slice(0, 20);\n const aiInstructions = [...new Set([...AI_FILES.filter(has), ...claudeFiles])].sort();\n const { docs, omitted: docsOmitted } = detectDocs(files, nodePkgs.map((p) => p.dir));\n const entryPoints = discoverEntryPoints(nodePkgs, files);\n\n const entryHints: string[] = [];\n for (const cand of ['src/index.ts', 'src/main.ts', 'src/app.ts', 'src/server.ts', 'index.js', 'server.js', 'app.js', 'main.py', 'app/main.py', 'main.go', 'cmd', 'src/main.rs', 'manage.py', 'src/App.tsx', 'app/layout.tsx']) {\n if (has(cand) || [...files].some((f) => f.startsWith(cand + '/'))) entryHints.push(cand);\n }\n\n const commands = buildContract({\n nodePackages: nodePkgs,\n ecosystems,\n has,\n pythonEvidence: py.evidence,\n files,\n });\n\n const languages = languagesFrom(scan.byExtension).slice(0, 12);\n if (ecosystems.size === 0 && languages.length > 0) {\n warnings.push(\n `No ecosystem was recognised although source files were found (${languages.slice(0, 3).map((l) => l.name).join(', ')}). Package manifests may be missing or unsupported; record verification commands by hand in .devworkspace/context/commands.json.`,\n );\n }\n if (ecosystems.size > 0 && !commands.some((c) => c.available)) {\n warnings.push('No verification commands (tests, lint, typecheck, build) were found in the package manifests.');\n }\n if (docsOmitted > 0) warnings.push(`${docsOmitted} more documentation file(s) were found than are listed (limit ${MAX_DOCS}).`);\n if (scan.truncated) warnings.push('Scan hit its file or depth limit; discovery is partial.');\n if (scan.sensitiveFiles.length > 0) warnings.push('Credential-like files exist; their contents were not read.');\n if (!has('README.md') && !docs.some((d) => /^readme/i.test(d))) warnings.push('No README found.');\n\n return {\n schemaVersion: 1,\n project: { name: rootPkg?.name ?? input.projectName },\n scan: {\n fileCount: scan.fileCount,\n dirCount: scan.dirCount,\n truncated: scan.truncated,\n skippedSymlinks: scan.skippedSymlinks,\n ignoredEntries: scan.ignoredEntries,\n },\n languages,\n topDirs: scan.topDirs,\n ecosystems: [...ecosystems].sort(),\n packageManager,\n frameworks: [...frameworks.values()].sort((a, b) => a.name.localeCompare(b.name)),\n monorepo: { tool: monoTool, packages },\n commands,\n manifests: [...nodePkgs.map((p) => p.manifest), ...['pyproject.toml', 'requirements.txt', 'Pipfile', 'go.mod', 'Cargo.toml', 'pom.xml', 'build.gradle', 'build.gradle.kts', 'composer.json', 'Gemfile'].filter(has)].sort(),\n testConfigs,\n ci,\n docker,\n deployment,\n aiInstructions,\n docs,\n sensitiveFilesPresent: scan.sensitiveFiles.filter((f) => isSensitiveFile(f)),\n entryHints,\n entryPoints,\n warnings,\n };\n}\n"]}
@@ -0,0 +1,10 @@
1
+ export declare const MAX_DOCS = 40;
2
+ /**
3
+ * Documentation worth pointing an agent at: top-level READMEs and notes, Markdown in docs/adr/architecture directories
4
+ * (also inside packages such as backend/docs), and READMEs of packages. Pure function of the scanned file set, so it is
5
+ * deterministic; generated and dependency directories were already excluded by the scan.
6
+ */
7
+ export declare function detectDocs(files: Iterable<string>, packageDirs: string[]): {
8
+ docs: string[];
9
+ omitted: number;
10
+ };
@@ -0,0 +1,52 @@
1
+ import path from 'node:path';
2
+ const DOC_FILE = /\.(?:md|mdx|rst)$/i;
3
+ const DOC_DIR = /^(?:docs?|documentation|adrs?|architecture|decisions?)$/i;
4
+ const TOP_LEVEL = /^(?:readme(?:\.[a-z]+)?|contributing\.md|architecture\.md|changelog\.md)$/i;
5
+ const PACKAGE_LEVEL = /^(?:readme|architecture|contributing)\.(?:md|mdx|rst)$/i;
6
+ /** Directories whose Markdown is sample data, not the project's own documentation. */
7
+ const SAMPLE_DIRS = new Set(['fixtures', 'fixture', '__fixtures__', 'examples', 'example', 'samples', 'sample', 'testdata', 'test-data', 'demo', 'demos', 'third_party', 'thirdparty']);
8
+ export const MAX_DOCS = 40;
9
+ const MAX_DEPTH = 6;
10
+ const MAX_DOC_DIR_INDEX = 2; // docs/ may sit at most two directories below the root: backend/docs, apps/api/docs
11
+ /** Files that matter most when the list has to be cut: indexes, architecture notes, ADRs and READMEs. */
12
+ function priority(file) {
13
+ const name = path.posix.basename(file);
14
+ if (/^readme/i.test(name))
15
+ return 0;
16
+ if (/(?:^|[/_-])(?:index|architecture|overview|quick[_-]?start|adrs?[-_]?\d*)(?=[/_.-]|$)/i.test(file))
17
+ return 1;
18
+ return 2;
19
+ }
20
+ /**
21
+ * Documentation worth pointing an agent at: top-level READMEs and notes, Markdown in docs/adr/architecture directories
22
+ * (also inside packages such as backend/docs), and READMEs of packages. Pure function of the scanned file set, so it is
23
+ * deterministic; generated and dependency directories were already excluded by the scan.
24
+ */
25
+ export function detectDocs(files, packageDirs) {
26
+ const pkgReadmes = new Set(packageDirs.filter((d) => d !== '').map((d) => d));
27
+ const found = new Set();
28
+ for (const f of files) {
29
+ if (!DOC_FILE.test(f))
30
+ continue;
31
+ const segs = f.split('/');
32
+ if (segs.length > MAX_DEPTH)
33
+ continue;
34
+ const dirs = segs.slice(0, -1);
35
+ const name = segs[segs.length - 1];
36
+ if (dirs.length === 0) {
37
+ if (TOP_LEVEL.test(name))
38
+ found.add(f);
39
+ continue;
40
+ }
41
+ const docIdx = dirs.findIndex((s) => DOC_DIR.test(s));
42
+ if (docIdx !== -1 && docIdx <= MAX_DOC_DIR_INDEX && !dirs.slice(0, docIdx).some((s) => SAMPLE_DIRS.has(s.toLowerCase()))) {
43
+ found.add(f);
44
+ continue;
45
+ }
46
+ if (PACKAGE_LEVEL.test(name) && pkgReadmes.has(dirs.join('/')) && !dirs.some((s) => SAMPLE_DIRS.has(s.toLowerCase())))
47
+ found.add(f);
48
+ }
49
+ const all = [...found].sort((a, b) => priority(a) - priority(b) || a.localeCompare(b));
50
+ return { docs: all.slice(0, MAX_DOCS).sort(), omitted: Math.max(0, all.length - MAX_DOCS) };
51
+ }
52
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/discovery/docs.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\n\nconst DOC_FILE = /\\.(?:md|mdx|rst)$/i;\nconst DOC_DIR = /^(?:docs?|documentation|adrs?|architecture|decisions?)$/i;\nconst TOP_LEVEL = /^(?:readme(?:\\.[a-z]+)?|contributing\\.md|architecture\\.md|changelog\\.md)$/i;\nconst PACKAGE_LEVEL = /^(?:readme|architecture|contributing)\\.(?:md|mdx|rst)$/i;\n/** Directories whose Markdown is sample data, not the project's own documentation. */\nconst SAMPLE_DIRS = new Set(['fixtures', 'fixture', '__fixtures__', 'examples', 'example', 'samples', 'sample', 'testdata', 'test-data', 'demo', 'demos', 'third_party', 'thirdparty']);\n\nexport const MAX_DOCS = 40;\nconst MAX_DEPTH = 6;\nconst MAX_DOC_DIR_INDEX = 2; // docs/ may sit at most two directories below the root: backend/docs, apps/api/docs\n\n/** Files that matter most when the list has to be cut: indexes, architecture notes, ADRs and READMEs. */\nfunction priority(file: string): number {\n const name = path.posix.basename(file);\n if (/^readme/i.test(name)) return 0;\n if (/(?:^|[/_-])(?:index|architecture|overview|quick[_-]?start|adrs?[-_]?\\d*)(?=[/_.-]|$)/i.test(file)) return 1;\n return 2;\n}\n\n/**\n * Documentation worth pointing an agent at: top-level READMEs and notes, Markdown in docs/adr/architecture directories\n * (also inside packages such as backend/docs), and READMEs of packages. Pure function of the scanned file set, so it is\n * deterministic; generated and dependency directories were already excluded by the scan.\n */\nexport function detectDocs(files: Iterable<string>, packageDirs: string[]): { docs: string[]; omitted: number } {\n const pkgReadmes = new Set(packageDirs.filter((d) => d !== '').map((d) => d));\n const found = new Set<string>();\n for (const f of files) {\n if (!DOC_FILE.test(f)) continue;\n const segs = f.split('/');\n if (segs.length > MAX_DEPTH) continue;\n const dirs = segs.slice(0, -1);\n const name = segs[segs.length - 1]!;\n if (dirs.length === 0) {\n if (TOP_LEVEL.test(name)) found.add(f);\n continue;\n }\n const docIdx = dirs.findIndex((s) => DOC_DIR.test(s));\n if (docIdx !== -1 && docIdx <= MAX_DOC_DIR_INDEX && !dirs.slice(0, docIdx).some((s) => SAMPLE_DIRS.has(s.toLowerCase()))) {\n found.add(f);\n continue;\n }\n if (PACKAGE_LEVEL.test(name) && pkgReadmes.has(dirs.join('/')) && !dirs.some((s) => SAMPLE_DIRS.has(s.toLowerCase()))) found.add(f);\n }\n const all = [...found].sort((a, b) => priority(a) - priority(b) || a.localeCompare(b));\n return { docs: all.slice(0, MAX_DOCS).sort(), omitted: Math.max(0, all.length - MAX_DOCS) };\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import type { PackageInfo } from './detect.js';
2
+ export type EntryKind = 'server' | 'worker' | 'main' | 'cli';
3
+ export interface EntryPoint {
4
+ /** Path relative to the package directory (POSIX). */
5
+ path: string;
6
+ /** The package directory relative to the project root; "." for the root package. */
7
+ cwd: string;
8
+ kind: EntryKind;
9
+ /** Where the evidence came from, e.g. `backend/package.json#scripts.dev`. */
10
+ evidence: string;
11
+ }
12
+ /**
13
+ * Entry points that a package itself declares: files named by its start-like scripts, its `main` and its `bin`.
14
+ * A file is never an entry point just because it is called server.ts, worker.ts or index.ts.
15
+ */
16
+ export declare function discoverEntryPoints(packages: {
17
+ dir: string;
18
+ pkg: PackageInfo;
19
+ manifest: string;
20
+ }[], files: Set<string>): EntryPoint[];
@@ -0,0 +1,67 @@
1
+ import path from 'node:path';
2
+ /** Script names that start a long-running process. Everything else (build, test, db:migrate, ...) is not an entry point. */
3
+ const RUN_SCRIPT = /^(?:dev|start|serve|server|watch|worker|workers|queue|consumer)(?::.+)?$/;
4
+ const WORKER_HINT = /worker|queue|consumer/i;
5
+ const FILE_TOKEN = /(?:^|[\s"'=;&|])((?:\.{1,2}\/)?[\w@./-]+\.(?:[cm]?[jt]s|[jt]sx))(?=$|[\s"';&|])/g;
6
+ const NOT_AN_ENTRY = /\.(?:config|test|spec|d)\.[cm]?[jt]s$|(^|\/)(?:node_modules|dist|build)\//;
7
+ const OUTPUT_DIR = /^(?:\.\/)?(?:dist|build|out|lib)\//;
8
+ const SOURCE_EXT = ['.ts', '.tsx', '.mts', '.cts', '.js', '.mjs', '.cjs', '.jsx'];
9
+ function resolveIn(files, dir, token) {
10
+ const rel = (p) => path.posix.normalize(dir ? `${dir}/${p}` : p);
11
+ const direct = rel(token.replace(/^\.\//, ''));
12
+ if (!OUTPUT_DIR.test(token) && files.has(direct))
13
+ return direct;
14
+ if (OUTPUT_DIR.test(token)) {
15
+ // `node dist/app/server.js` runs the compiled form of src/app/server.ts
16
+ const stem = token.replace(OUTPUT_DIR, '').replace(/\.[cm]?js$/, '');
17
+ for (const ext of SOURCE_EXT) {
18
+ const candidate = rel(`src/${stem}${ext}`);
19
+ if (files.has(candidate))
20
+ return candidate;
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ /**
26
+ * Entry points that a package itself declares: files named by its start-like scripts, its `main` and its `bin`.
27
+ * A file is never an entry point just because it is called server.ts, worker.ts or index.ts.
28
+ */
29
+ export function discoverEntryPoints(packages, files) {
30
+ const found = new Map();
31
+ const add = (dir, projectRel, kind, evidence) => {
32
+ const rel = dir ? projectRel.slice(dir.length + 1) : projectRel;
33
+ const key = `${dir}\u0000${rel}`;
34
+ const prev = found.get(key);
35
+ // A worker script wins over a generic server label for the same file.
36
+ if (!prev || (kind === 'worker' && prev.kind !== 'worker'))
37
+ found.set(key, { path: rel, cwd: dir || '.', kind, evidence });
38
+ };
39
+ for (const { dir, pkg, manifest } of packages) {
40
+ for (const [name, body] of Object.entries(pkg.scripts)) {
41
+ if (!RUN_SCRIPT.test(name))
42
+ continue;
43
+ for (const m of body.matchAll(FILE_TOKEN)) {
44
+ const token = m[1];
45
+ if (token.startsWith('-') || NOT_AN_ENTRY.test(token.replace(OUTPUT_DIR, 'x/')))
46
+ continue;
47
+ const hit = resolveIn(files, dir, token);
48
+ if (!hit)
49
+ continue;
50
+ add(dir, hit, WORKER_HINT.test(name) || WORKER_HINT.test(path.posix.basename(hit)) ? 'worker' : 'server', `${manifest}#scripts.${name}`);
51
+ }
52
+ }
53
+ if (pkg.main) {
54
+ const hit = resolveIn(files, dir, pkg.main);
55
+ if (hit && !NOT_AN_ENTRY.test(hit))
56
+ add(dir, hit, 'main', `${manifest}#main`);
57
+ }
58
+ for (const bin of pkg.bin ?? []) {
59
+ const hit = resolveIn(files, dir, bin);
60
+ if (hit && !NOT_AN_ENTRY.test(hit))
61
+ add(dir, hit, 'cli', `${manifest}#bin`);
62
+ }
63
+ }
64
+ const order = { server: 0, worker: 1, main: 2, cli: 3 };
65
+ return [...found.values()].sort((a, b) => a.cwd.localeCompare(b.cwd) || order[a.kind] - order[b.kind] || a.path.localeCompare(b.path)).slice(0, 60);
66
+ }
67
+ //# sourceMappingURL=entrypoints.js.map