@thanh01.pmt/domain-kit 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +682 -168
  2. package/dist/assembly/index.d.cts +2 -2
  3. package/dist/assembly/index.d.ts +2 -2
  4. package/dist/{chunk-HILSUZOF.mjs → chunk-2OGNQUXC.mjs} +171 -31
  5. package/dist/chunk-2OGNQUXC.mjs.map +1 -0
  6. package/dist/{chunk-LZQLLAYP.mjs → chunk-5OMSYKQP.mjs} +43 -23
  7. package/dist/chunk-5OMSYKQP.mjs.map +1 -0
  8. package/dist/{chunk-BL5NBKPH.mjs → chunk-67GXK3ZE.mjs} +18 -8
  9. package/dist/chunk-67GXK3ZE.mjs.map +1 -0
  10. package/dist/{chunk-PKUEOSZ3.mjs → chunk-CGNXGVHV.mjs} +46 -4
  11. package/dist/chunk-CGNXGVHV.mjs.map +1 -0
  12. package/dist/{chunk-VCPIWJ7R.mjs → chunk-ERDTHXQA.mjs} +21 -3
  13. package/dist/chunk-ERDTHXQA.mjs.map +1 -0
  14. package/dist/chunk-OYSZQVPY.mjs +10 -0
  15. package/dist/chunk-OYSZQVPY.mjs.map +1 -0
  16. package/dist/{chunk-QJF4QCBJ.mjs → chunk-WKTH3JPA.mjs} +202 -36
  17. package/dist/chunk-WKTH3JPA.mjs.map +1 -0
  18. package/dist/{conceptEscalator-YfMKIKCZ.d.ts → conceptEscalator-BCsw0ys_.d.ts} +10 -1
  19. package/dist/{conceptEscalator-ltRLtPhf.d.cts → conceptEscalator-DPrs4PwC.d.cts} +10 -1
  20. package/dist/concepts/index.d.cts +1 -1
  21. package/dist/concepts/index.d.ts +1 -1
  22. package/dist/{curriculumFeedSchema-B66H3gEV.d.ts → curriculumFeedSchema-DYayelAA.d.cts} +212 -1
  23. package/dist/{curriculumFeedSchema-B66H3gEV.d.cts → curriculumFeedSchema-DYayelAA.d.ts} +212 -1
  24. package/dist/detector/index.cjs +21 -6
  25. package/dist/detector/index.cjs.map +1 -1
  26. package/dist/detector/index.mjs +2 -1
  27. package/dist/feed/index.cjs +243 -33
  28. package/dist/feed/index.cjs.map +1 -1
  29. package/dist/feed/index.d.cts +32 -2
  30. package/dist/feed/index.d.ts +32 -2
  31. package/dist/feed/index.mjs +2 -2
  32. package/dist/graph/index.cjs +163 -28
  33. package/dist/graph/index.cjs.map +1 -1
  34. package/dist/graph/index.d.cts +14 -5
  35. package/dist/graph/index.d.ts +14 -5
  36. package/dist/graph/index.mjs +2 -1
  37. package/dist/{hybridGraphPipeline-DXQDbBEj.d.ts → hybridGraphPipeline-9dRKJj7r.d.ts} +6 -2
  38. package/dist/{hybridGraphPipeline-dT-bio-3.d.cts → hybridGraphPipeline-CocfYe4d.d.cts} +6 -2
  39. package/dist/{hybridGraphSchema-nrUeSwpU.d.ts → hybridGraphSchema-C37qxdTM.d.cts} +16 -3
  40. package/dist/{hybridGraphSchema-nrUeSwpU.d.cts → hybridGraphSchema-C37qxdTM.d.ts} +16 -3
  41. package/dist/index.cjs +3742 -3362
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.d.cts +6 -6
  44. package/dist/index.d.ts +6 -6
  45. package/dist/index.mjs +7 -6
  46. package/dist/llmClient-CX5uUiQ1.d.cts +60 -0
  47. package/dist/llmClient-CX5uUiQ1.d.ts +60 -0
  48. package/dist/pipeline/index.cjs +1556 -1202
  49. package/dist/pipeline/index.cjs.map +1 -1
  50. package/dist/pipeline/index.d.cts +13 -5
  51. package/dist/pipeline/index.d.ts +13 -5
  52. package/dist/pipeline/index.mjs +6 -5
  53. package/dist/schemas/index.cjs +64 -2
  54. package/dist/schemas/index.cjs.map +1 -1
  55. package/dist/schemas/index.d.cts +2 -2
  56. package/dist/schemas/index.d.ts +2 -2
  57. package/dist/schemas/index.mjs +2 -2
  58. package/package.json +1 -1
  59. package/dist/chunk-BL5NBKPH.mjs.map +0 -1
  60. package/dist/chunk-HILSUZOF.mjs.map +0 -1
  61. package/dist/chunk-LZQLLAYP.mjs.map +0 -1
  62. package/dist/chunk-PKUEOSZ3.mjs.map +0 -1
  63. package/dist/chunk-QJF4QCBJ.mjs.map +0 -1
  64. package/dist/chunk-VCPIWJ7R.mjs.map +0 -1
  65. package/dist/curriculumFeedEmitter-6IK6PFDH.mjs +0 -4
  66. package/dist/curriculumFeedEmitter-6IK6PFDH.mjs.map +0 -1
  67. package/dist/llmClient-ysPhLjcH.d.cts +0 -16
  68. package/dist/llmClient-ysPhLjcH.d.ts +0 -16
@@ -1,8 +1,8 @@
1
- import { emitCurriculumFeed } from './chunk-QJF4QCBJ.mjs';
1
+ import { emitCurriculumFeed } from './chunk-WKTH3JPA.mjs';
2
2
  import { parseSwiftFile, parseTsFile, parsePythonFile, parseCppFile, mergeSwiftResults, mergeTsResults, mergePythonResults, mergeCppResults } from './chunk-DRVOV5ZD.mjs';
3
3
  import { extractKeywords } from './chunk-XMHKWHVK.mjs';
4
- import { detectDomainProfile } from './chunk-BL5NBKPH.mjs';
5
- import { extractScaffold, extractProjectOverview, extractFeatureStepsBatched, extractFeatureSteps, verifyProjectGraph, escalateAndMapConcepts, generateKnowledgeGraph, generateHybridGraph, createLlmClient, llmChatJson } from './chunk-HILSUZOF.mjs';
4
+ import { detectDomainProfile } from './chunk-67GXK3ZE.mjs';
5
+ import { createLlmClient, extractScaffold, extractProjectOverview, extractFeatureStepsBatched, extractFeatureSteps, verifyProjectGraph, escalateAndMapConcepts, generateKnowledgeGraph, summarizeProvenance, generateHybridGraph, llmChatJson } from './chunk-2OGNQUXC.mjs';
6
6
  import { parseSyllabus } from './chunk-T4Y2DE2W.mjs';
7
7
  import { resolveConcepts } from './chunk-KNDBODUQ.mjs';
8
8
  import { assembleRoadmap } from './chunk-ONQHJ4OH.mjs';
@@ -11,11 +11,11 @@ import { relative, join, extname } from 'path';
11
11
  import { execSync } from 'child_process';
12
12
 
13
13
  // src/extractors/fileSelector.ts
14
- async function selectFilesWithLlm(filePaths, goal, techStack, llmConfig) {
14
+ async function selectFilesWithLlm(filePaths, goal, techStack, llmConfig, sharedClient) {
15
15
  if (filePaths.length <= 15) {
16
16
  return { selected: filePaths, reasoning: "Too few files to filter" };
17
17
  }
18
- const client = createLlmClient(llmConfig);
18
+ const client = sharedClient ?? createLlmClient(llmConfig);
19
19
  const treeLines = buildFileTree(filePaths);
20
20
  const systemPrompt = 'You are a software architect analyzing a project repository.\nGiven a file tree and a project goal, select which files are MOST IMPORTANT to read for understanding the project architecture and implementation.\n\nRULES:\n1. Prioritize source code files (Swift, TS, Python, C++) over config/docs\n2. Include entry points (App.swift, main.py, index.ts)\n3. Include core domain files (models, services, views, controllers)\n4. EXCLUDE test files, mock files, generated files\n5. EXCLUDE config files (package.json, Podfile, etc.) unless they reveal architecture\n6. Include files that directly implement the features mentioned in the goal\n7. Return 20-40 files maximum (fewer is better if the project is small)\n\nReturn JSON: {"selected": ["path/to/file1", "path/to/file2"], "reasoning": "brief explanation"}';
21
21
  const userPrompt = `Project goal: ${goal}
@@ -177,6 +177,7 @@ function detectPrimaryLanguage(filePaths) {
177
177
  }
178
178
  async function runProjectGraphPipeline(options) {
179
179
  const { repoDir, goal, techStack, llmConfig, embeddings, onProgress } = options;
180
+ const client = createLlmClient(llmConfig);
180
181
  const log = (step, msg) => {
181
182
  console.log(`[${step}] ${msg}`);
182
183
  onProgress?.(step, msg);
@@ -190,7 +191,8 @@ async function runProjectGraphPipeline(options) {
190
191
  allRelPaths,
191
192
  goal,
192
193
  techStack,
193
- llmConfig
194
+ llmConfig,
195
+ client
194
196
  );
195
197
  log("STEP_1", `LLM selected ${selectedPaths.length}/${allRelPaths.length} files: ${reasoning.slice(0, 100)}`);
196
198
  log("STEP_1", "Reading content for selected files...");
@@ -239,7 +241,8 @@ async function runProjectGraphPipeline(options) {
239
241
  goal,
240
242
  techStack,
241
243
  fileList: filePaths,
242
- llmConfig
244
+ llmConfig,
245
+ sharedClient: client
243
246
  });
244
247
  log("STEP_4_C1", "Extracting project overview (features meta)...");
245
248
  const overview = await extractProjectOverview({
@@ -248,7 +251,8 @@ async function runProjectGraphPipeline(options) {
248
251
  sdkApiIndex,
249
252
  fileContentsMap,
250
253
  astKeywords,
251
- llmConfig
254
+ llmConfig,
255
+ sharedClient: client
252
256
  });
253
257
  const product = overview.product;
254
258
  const pblStep = {
@@ -301,7 +305,8 @@ async function runProjectGraphPipeline(options) {
301
305
  sdkApiIndex,
302
306
  fileContentsMap,
303
307
  nonF0Features,
304
- llmConfig
308
+ llmConfig,
309
+ client
305
310
  );
306
311
  for (const feature of nonF0Features) {
307
312
  const steps = batchedSteps.get(feature.id || "");
@@ -317,7 +322,8 @@ async function runProjectGraphPipeline(options) {
317
322
  sdkApiIndex,
318
323
  fileContentsMap,
319
324
  feature,
320
- llmConfig
325
+ llmConfig,
326
+ sharedClient: client
321
327
  });
322
328
  feature.steps = steps;
323
329
  } catch (e) {
@@ -371,7 +377,8 @@ async function runProjectGraphPipeline(options) {
371
377
  const featureConcepts = await escalateAndMapConcepts({
372
378
  projectGraph: verifiedGraph,
373
379
  fileContentsMap,
374
- llmConfig
380
+ llmConfig,
381
+ sharedClient: client
375
382
  });
376
383
  log("STEP_6", `Concept mapping complete: ${featureConcepts.size} features mapped`);
377
384
  for (const feature of verifiedGraph.features || []) {
@@ -440,7 +447,8 @@ async function runProjectGraphPipeline(options) {
440
447
  roadmap,
441
448
  hallucinations,
442
449
  keywords: astKeywords,
443
- featureConcepts
450
+ featureConcepts,
451
+ provenance: client.callLog
444
452
  };
445
453
  }
446
454
 
@@ -465,7 +473,8 @@ async function runKnowledgeGraphPipeline(options) {
465
473
  });
466
474
  warnings.push(...result.warnings);
467
475
  const curriculumFeed = emitCurriculumFeed(result.knowledgeGraph, {
468
- warnings
476
+ warnings,
477
+ provenance: summarizeProvenance(result.provenance)
469
478
  });
470
479
  return {
471
480
  knowledgeGraph: result.knowledgeGraph,
@@ -482,7 +491,8 @@ async function runHybridGraphPipeline(options) {
482
491
  const result = await generateHybridGraph(options);
483
492
  warnings.push(...result.warnings);
484
493
  const curriculumFeed = emitCurriculumFeed(result.hybridGraph, {
485
- warnings
494
+ warnings,
495
+ provenance: summarizeProvenance(result.provenance)
486
496
  });
487
497
  return {
488
498
  hybridGraph: result.hybridGraph,
@@ -528,6 +538,9 @@ async function runDomainPipeline(options) {
528
538
  }
529
539
  if (effectiveMode === "hybrid") {
530
540
  log("LAYER_3", "Executing Hybrid Graph Pipeline...");
541
+ if (!options.repoDir && options.forcedLearningMode === "hybrid") {
542
+ throw new Error('forcedLearningMode "hybrid" requires repoDir \u2014 refusing to silently degrade to a concept-only feed (fail-closed)');
543
+ }
531
544
  if (options.repoDir) {
532
545
  const projectResult2 = await runProjectGraphPipeline({
533
546
  repoDir: options.repoDir,
@@ -545,7 +558,9 @@ async function runDomainPipeline(options) {
545
558
  domain: domainProfile.domainCategory,
546
559
  techStack: options.techStack,
547
560
  llmConfig: options.llmConfig,
548
- onProgress: options.onProgress
561
+ onProgress: options.onProgress,
562
+ knowledgeTreePath: options.knowledgeTreePath,
563
+ proposalsPath: options.proposalsPath
549
564
  });
550
565
  const hybridResult = await runHybridGraphPipeline({
551
566
  projectGraph: projectResult2.projectGraph,
@@ -564,7 +579,8 @@ async function runDomainPipeline(options) {
564
579
  warnings
565
580
  };
566
581
  } else {
567
- warnings.push("Hybrid learning mode requested but repoDir was not provided \u2014 falling back to concept-driven knowledge graph pipeline");
582
+ const downgradeReason = "Hybrid learning mode requested but repoDir was not provided \u2014 falling back to concept-driven knowledge graph pipeline";
583
+ warnings.push(downgradeReason);
568
584
  const knowledgeResult = await runKnowledgeGraphPipeline({
569
585
  subject: options.subject || domainProfile.detectedSubject || options.goal || "Subject Theory",
570
586
  description: options.description,
@@ -573,7 +589,9 @@ async function runDomainPipeline(options) {
573
589
  domain: domainProfile.domainCategory,
574
590
  techStack: options.techStack,
575
591
  llmConfig: options.llmConfig,
576
- onProgress: options.onProgress
592
+ onProgress: options.onProgress,
593
+ knowledgeTreePath: options.knowledgeTreePath,
594
+ proposalsPath: options.proposalsPath
577
595
  });
578
596
  warnings.push(...knowledgeResult.warnings);
579
597
  return {
@@ -581,7 +599,8 @@ async function runDomainPipeline(options) {
581
599
  graphType: "knowledge_graph",
582
600
  curriculumFeed: knowledgeResult.curriculumFeed,
583
601
  knowledgeResult,
584
- warnings
602
+ warnings,
603
+ modeDowngrade: { from: "hybrid_graph", to: "knowledge_graph", reason: downgradeReason }
585
604
  };
586
605
  }
587
606
  }
@@ -597,9 +616,10 @@ async function runDomainPipeline(options) {
597
616
  embeddings: options.embeddings,
598
617
  onProgress: options.onProgress
599
618
  });
600
- const { emitCurriculumFeed: emitCurriculumFeed2 } = await import('./curriculumFeedEmitter-6IK6PFDH.mjs');
601
- const curriculumFeed = emitCurriculumFeed2(projectResult.projectGraph, {
602
- warnings
619
+ const curriculumFeed = emitCurriculumFeed(projectResult.projectGraph, {
620
+ warnings,
621
+ hallucinationCount: projectResult.hallucinations.length,
622
+ provenance: summarizeProvenance(projectResult.provenance)
603
623
  });
604
624
  return {
605
625
  domainProfile,
@@ -611,5 +631,5 @@ async function runDomainPipeline(options) {
611
631
  }
612
632
 
613
633
  export { runDomainPipeline, runHybridGraphPipeline, runKnowledgeGraphPipeline, runProjectGraphPipeline };
614
- //# sourceMappingURL=chunk-LZQLLAYP.mjs.map
615
- //# sourceMappingURL=chunk-LZQLLAYP.mjs.map
634
+ //# sourceMappingURL=chunk-5OMSYKQP.mjs.map
635
+ //# sourceMappingURL=chunk-5OMSYKQP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/extractors/fileSelector.ts","../src/utils/fileUtils.ts","../src/pipeline/projectGraphPipeline.ts","../src/pipeline/knowledgeGraphPipeline.ts","../src/pipeline/hybridGraphPipeline.ts","../src/pipeline/domainRouter.ts"],"names":["relative","projectResult"],"mappings":"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","file":"chunk-5OMSYKQP.mjs","sourcesContent":["/**\n * LLM-based File Selector — sends file tree to LLM, asks it to pick\n * which files are most relevant to the project goal.\n *\n * This mirrors knowledge-tree's approach:\n * 1. git_tracker generates project_structure.txt (file tree)\n * 2. Agent/LLM reads tree → selects important files\n * 3. Only selected files are read for analysis\n */\n\nimport { createLlmClient, llmChatJson, type LlmClientConfig, type LlmClient } from '../utils/llmClient';\n\nexport interface FileSelectionResult {\n selected: string[];\n reasoning: string;\n}\n\n/**\n * Ask LLM to select which files from the file tree are relevant to the goal.\n * Input: file tree (names only, very small) + goal\n * Output: list of file paths to analyze\n */\nexport async function selectFilesWithLlm(\n filePaths: string[],\n goal: string,\n techStack: string,\n llmConfig?: LlmClientConfig,\n sharedClient?: LlmClient,\n): Promise<FileSelectionResult> {\n // If very few files, no need to filter\n if (filePaths.length <= 15) {\n return { selected: filePaths, reasoning: 'Too few files to filter' };\n }\n\n const client = sharedClient ?? createLlmClient(llmConfig);\n\n // Build file tree for LLM (just names, grouped by directory)\n const treeLines = buildFileTree(filePaths);\n\n const systemPrompt = (\n 'You are a software architect analyzing a project repository.\\n'\n + 'Given a file tree and a project goal, select which files are MOST IMPORTANT '\n + 'to read for understanding the project architecture and implementation.\\n\\n'\n + 'RULES:\\n'\n + '1. Prioritize source code files (Swift, TS, Python, C++) over config/docs\\n'\n + '2. Include entry points (App.swift, main.py, index.ts)\\n'\n + '3. Include core domain files (models, services, views, controllers)\\n'\n + '4. EXCLUDE test files, mock files, generated files\\n'\n + '5. EXCLUDE config files (package.json, Podfile, etc.) unless they reveal architecture\\n'\n + '6. Include files that directly implement the features mentioned in the goal\\n'\n + '7. Return 20-40 files maximum (fewer is better if the project is small)\\n\\n'\n + 'Return JSON: {\"selected\": [\"path/to/file1\", \"path/to/file2\"], \"reasoning\": \"brief explanation\"}'\n );\n\n const userPrompt = (\n `Project goal: ${goal}\\n`\n + `Tech stack: ${techStack}\\n\\n`\n + `FILE TREE (${filePaths.length} files):\\n${treeLines}\\n\\n`\n + 'Select the most important files to analyze. Return JSON.'\n );\n\n try {\n const result = await llmChatJson(client, systemPrompt, userPrompt, {\n temperature: 0.1,\n maxTokens: 4096,\n });\n\n const selected = Array.isArray(result.selected) ? result.selected as string[] : [];\n const reasoning = String(result.reasoning || '');\n\n // Validate: only keep files that exist in the original list\n const pathSet = new Set(filePaths);\n const validSelected = selected.filter(p => pathSet.has(p));\n\n if (validSelected.length === 0) {\n // LLM returned nothing valid — fallback to all files\n return { selected: filePaths, reasoning: 'LLM selection empty, using all files' };\n }\n\n return { selected: validSelected, reasoning };\n } catch (err) {\n console.warn(`[WARN] LLM file selection failed (${err}), using all files`);\n return { selected: filePaths, reasoning: `LLM failed: ${err}` };\n }\n}\n\n/**\n * Build a compact file tree string for LLM consumption.\n * Groups files by top-level directory, shows only filenames.\n */\nfunction buildFileTree(filePaths: string[]): string {\n const byDir = new Map<string, string[]>();\n\n for (const fp of filePaths) {\n const parts = fp.split('/');\n const dir = parts.length > 1 ? parts.slice(0, -1).join('/') : '(root)';\n const file = parts[parts.length - 1];\n if (!byDir.has(dir)) byDir.set(dir, []);\n byDir.get(dir)!.push(file);\n }\n\n const lines: string[] = [];\n for (const [dir, files] of byDir) {\n lines.push(`${dir}/`);\n for (const f of files.sort()) {\n lines.push(` ${f}`);\n }\n }\n\n return lines.join('\\n');\n}\n","/**\n * File I/O utilities for domain-kit pipeline.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync } from 'node:fs';\nimport { join, extname, relative, resolve } from 'node:path';\nimport { execSync } from 'node:child_process';\n\n/**\n * Read JSON file safely, returns null if not found or invalid.\n */\nexport function readJsonFile<T = unknown>(filePath: string): T | null {\n try {\n if (!existsSync(filePath)) return null;\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n/**\n * Write JSON file, creating parent directories if needed.\n */\nexport function writeJsonFile(filePath: string, data: unknown): void {\n mkdirSync(join(filePath, '..'), { recursive: true });\n writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\n/**\n * Read text file safely, returns null if not found.\n */\nexport function readTextFile(filePath: string): string | null {\n try {\n if (!existsSync(filePath)) return null;\n return readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Collect source files from a directory, filtering by allowed extensions.\n */\nexport function collectSourceFiles(\n dir: string,\n options?: {\n allowedExtensions?: string[];\n skipDirs?: string[];\n maxFiles?: number;\n },\n): string[] {\n const allowedExts = options?.allowedExtensions || ['.swift', '.ts', '.tsx', '.js', '.jsx', '.py', '.ino', '.cpp', '.c', '.h', '.hpp'];\n const maxFiles = options?.maxFiles || 70;\n\n // Try git ls-files first — respects .gitignore, handles submodules, symlinks\n const gitFiles = collectViaGit(dir, allowedExts, maxFiles);\n if (gitFiles.length > 0) return gitFiles;\n\n // Fallback: filesystem walk (non-git directories)\n return collectViaFilesystem(dir, allowedExts, maxFiles, options?.skipDirs);\n}\n\n/**\n * Collect source files using `git ls-files`.\n * Respects .gitignore, handles symlinks, much faster than walk.\n */\nfunction collectViaGit(dir: string, allowedExts: string[], maxFiles: number): string[] {\n try {\n const raw = execSync('git ls-files --cached --others --exclude-standard', {\n cwd: dir,\n encoding: 'utf-8',\n timeout: 5000,\n maxBuffer: 1024 * 1024,\n });\n const extSet = new Set(allowedExts.map(e => e.toLowerCase()));\n return raw\n .split('\\n')\n .filter(line => line.length > 0)\n .filter(line => extSet.has(extname(line).toLowerCase()))\n .slice(0, maxFiles)\n .map(rel => join(dir, rel));\n } catch {\n // Not a git repo or git not available — fall through to filesystem walk\n return [];\n }\n}\n\n/**\n * Collect source files using recursive directory walk (non-git fallback).\n */\nfunction collectViaFilesystem(\n dir: string,\n allowedExts: string[],\n maxFiles: number,\n skipDirs?: string[],\n): string[] {\n const skipSet = new Set(skipDirs || [\n 'node_modules', '.build', 'Pods', '.git', '.venv', 'venv',\n '__pycache__', 'build', 'dist', '.idea', '.vscode',\n 'test', 'tests', 'demo', 'sample', 'example', 'playground',\n ]);\n const extSet = new Set(allowedExts.map(e => e.toLowerCase()));\n const result: string[] = [];\n\n function walk(currentDir: string) {\n if (result.length >= maxFiles) return;\n let entries;\n try {\n entries = readdirSync(currentDir, { withFileTypes: true });\n } catch {\n return; // permission error\n }\n for (const entry of entries) {\n if (result.length >= maxFiles) return;\n const fullPath = join(currentDir, entry.name);\n if (entry.isDirectory()) {\n if (!skipSet.has(entry.name)) {\n walk(fullPath);\n }\n } else if (entry.isFile()) {\n const ext = extname(entry.name).toLowerCase();\n if (extSet.has(ext)) {\n result.push(fullPath);\n }\n }\n }\n }\n\n walk(dir);\n return result;\n}\n\n/**\n * Collect file contents map (relative path → content).\n */\nexport function collectFileContents(\n dir: string,\n options?: {\n allowedExtensions?: string[];\n skipDirs?: string[];\n maxFiles?: number;\n maxChars?: number;\n },\n): { paths: string[]; contents: Map<string, string> } {\n const maxChars = options?.maxChars || 500000;\n const files = collectSourceFiles(dir, options);\n const contents = new Map<string, string>();\n let totalChars = 0;\n\n for (const filePath of files) {\n const relPath = relative(dir, filePath);\n try {\n const content = readFileSync(filePath, 'utf-8');\n if (totalChars + content.length > maxChars) {\n const remaining = maxChars - totalChars;\n if (remaining > 100) {\n contents.set(relPath, content.slice(0, remaining));\n totalChars += remaining;\n }\n break;\n }\n contents.set(relPath, content);\n totalChars += content.length;\n } catch {\n // Skip unreadable files\n }\n }\n\n return { paths: files.map(f => relative(dir, f)), contents };\n}\n\n/**\n * Read contents of SPECIFIC files (by relative path) — no directory scan.\n * Used for 2-pass approach: scan tree first, then read only selected files.\n */\nexport function collectSpecificFileContents(\n dir: string,\n relativePaths: string[],\n maxChars: number = 500000,\n): Map<string, string> {\n const contents = new Map<string, string>();\n let totalChars = 0;\n\n for (const relPath of relativePaths) {\n const fullPath = join(dir, relPath);\n try {\n const content = readFileSync(fullPath, 'utf-8');\n if (totalChars + content.length > maxChars) {\n const remaining = maxChars - totalChars;\n if (remaining > 100) {\n contents.set(relPath, content.slice(0, remaining));\n totalChars += remaining;\n }\n break;\n }\n contents.set(relPath, content);\n totalChars += content.length;\n } catch {\n // Skip unreadable files\n }\n }\n\n return contents;\n}\n\n/**\n * Detect primary language from file extensions.\n */\nexport function detectPrimaryLanguage(filePaths: string[]): string {\n const counts = new Map<string, number>();\n for (const fp of filePaths) {\n const ext = extname(fp).toLowerCase();\n let lang = 'unknown';\n if (ext === '.swift') lang = 'Swift';\n else if (ext === '.ts' || ext === '.tsx') lang = 'TypeScript';\n else if (ext === '.js' || ext === '.jsx') lang = 'JavaScript';\n else if (ext === '.py') lang = 'Python';\n else if (ext === '.ino' || ext === '.cpp' || ext === '.c' || ext === '.h') lang = 'C++';\n else if (ext === '.kt' || ext === '.kts') lang = 'Kotlin';\n counts.set(lang, (counts.get(lang) || 0) + 1);\n }\n\n let maxCount = 0;\n let primary = 'unknown';\n for (const [lang, count] of counts) {\n if (count > maxCount) {\n maxCount = count;\n primary = lang;\n }\n }\n return primary;\n}\n\n/**\n * Read README.md and extract project description.\n */\nexport function readReadmeDescription(repoDir: string): string | null {\n const readmePath = join(repoDir, 'README.md');\n if (!existsSync(readmePath)) return null;\n try {\n const content = readFileSync(readmePath, 'utf-8');\n const lines = content.split('\\n').map(l => l.trim()).filter(Boolean);\n // Skip patterns: badges, images, table of contents, HTML tags\n const skipPatterns = [/^\\[!/, /^<img/, /^<a /, /^#+\\s+Table of/i, /^---$/];\n let foundTitle = false;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.startsWith('#') && !line.startsWith('##')) {\n foundTitle = true;\n continue;\n }\n if (!foundTitle) continue;\n // Skip empty lines, badges, images, TOC, horizontal rules\n if (skipPatterns.some(p => p.test(line))) continue;\n if (line.startsWith('#')) return null; // hit next heading — no description found\n if (line.startsWith('```')) return null; // code block\n if (line.startsWith('|')) return null; // table\n if (line.length > 15) return line;\n }\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * Project Graph Pipeline — full orchestrator.\n *\n * Ported from knowledge-tree/generate_roadmap_v3.py PipelineOrchestrator\n * Coordinates: AST analysis → keyword extraction → LLM graph generation →\n * verification → concept escalation → concept resolution → assembly.\n */\n\nimport type { ProjectGraph, Feature } from '../schemas/projectGraphSchema';\nimport { parseSwiftFile, mergeSwiftResults, type SwiftParseResult } from '../parsers/swift';\nimport { parseTsFile, mergeTsResults, type TsParseResult } from '../parsers/typescript';\nimport { parsePythonFile, mergePythonResults, type PythonParseResult } from '../parsers/python';\nimport { parseCppFile, mergeCppResults, type CppParseResult } from '../parsers/cpp';\nimport { extractKeywords, type Keyword, type SourceContext } from '../extractors/keywordExtractor';\nimport { extractScaffold } from '../graph/scaffoldExtractor';\nimport { extractProjectOverview } from '../graph/overviewExtractor';\nimport { extractFeatureSteps, extractFeatureStepsBatched } from '../graph/stepExtractor';\nimport { verifyProjectGraph, type Hallucination } from '../graph/graphVerifier';\nimport { escalateAndMapConcepts, type ConceptMapping } from '../graph/conceptEscalator';\nimport { resolveConcepts, type ResolveConceptsResult } from '../concepts/conceptResolver';\nimport { assembleRoadmap, type AssembledRoadmap } from '../assembly/roadmapAssembler';\nimport { selectFilesWithLlm } from '../extractors/fileSelector';\nimport { collectSourceFiles, collectSpecificFileContents, detectPrimaryLanguage, readReadmeDescription } from '../utils/fileUtils';\nimport { relative } from 'node:path';\nimport { createLlmClient, type LlmClientConfig, type LlmCallRecord } from '../utils/llmClient';\n\nexport interface PipelineOptions {\n repoDir: string;\n goal: string;\n techStack: string;\n llmConfig?: LlmClientConfig;\n embeddings?: Record<string, { embedding?: number[]; name?: string; description?: string; keywords?: string }>;\n onProgress?: (step: string, message: string) => void;\n}\n\nexport interface PipelineResult {\n projectGraph: ProjectGraph;\n resolvedConcepts: ResolveConceptsResult;\n roadmap: AssembledRoadmap;\n hallucinations: Hallucination[];\n keywords: Keyword[];\n featureConcepts: Map<string, ConceptMapping[]>;\n /** Which providers served this graph, and whether any call fell over. */\n provenance: LlmCallRecord[];\n}\n\n/**\n * Run the full project graph generation pipeline.\n */\nexport async function runProjectGraphPipeline(\n options: PipelineOptions,\n): Promise<PipelineResult> {\n const { repoDir, goal, techStack, llmConfig, embeddings, onProgress } = options;\n // One client for the whole run: pacing stays process-wide but every call lands in\n // a single callLog, so the emitted feed can name the providers that served it.\n const client = createLlmClient(llmConfig);\n\n const log = (step: string, msg: string) => {\n console.log(`[${step}] ${msg}`);\n onProgress?.(step, msg);\n };\n\n // ─── STEP 1A: File Tree Scan (names only — no content reading) ─────────\n log('STEP_1', 'Scanning file tree (names only)...');\n\n const allFilePaths = collectSourceFiles(repoDir);\n const allRelPaths = allFilePaths.map(fp => relative(repoDir, fp));\n log('STEP_1', `Found ${allRelPaths.length} source files in repository`);\n\n // ─── STEP 1B: LLM File Selection (sends tiny file tree to LLM) ────────\n log('STEP_1', 'Asking LLM to select relevant files from file tree...');\n\n const { selected: selectedPaths, reasoning } = await selectFilesWithLlm(\n allRelPaths, goal, techStack, llmConfig, client,\n );\n log('STEP_1', `LLM selected ${selectedPaths.length}/${allRelPaths.length} files: ${reasoning.slice(0, 100)}`);\n\n // ─── STEP 1C: Read content only for LLM-selected files ─────────────────\n log('STEP_1', 'Reading content for selected files...');\n\n const fileContentsMap = collectSpecificFileContents(repoDir, selectedPaths);\n const filePaths = selectedPaths;\n const primaryLang = detectPrimaryLanguage(filePaths);\n log('STEP_1', `Primary language: ${primaryLang}, ${filePaths.length} files loaded (${fileContentsMap.size} with content)`);\n\n // Parse source files\n log('STEP_1', 'Parsing source files with AST-level analysis...');\n\n const allParseResults: SourceContext[] = [];\n for (const [relPath, content] of fileContentsMap) {\n const fullPath = relPath;\n if (fullPath.endsWith('.swift')) {\n allParseResults.push(parseSwiftFile(fullPath, content));\n } else if (fullPath.endsWith('.ts') || fullPath.endsWith('.tsx') || fullPath.endsWith('.js') || fullPath.endsWith('.jsx')) {\n allParseResults.push(parseTsFile(fullPath, content));\n } else if (fullPath.endsWith('.py')) {\n allParseResults.push(parsePythonFile(fullPath, content));\n } else if (fullPath.endsWith('.ino') || fullPath.endsWith('.cpp') || fullPath.endsWith('.c') || fullPath.endsWith('.h')) {\n allParseResults.push(parseCppFile(fullPath, content));\n }\n }\n\n // Merge parse results by language\n let mergedContext: SourceContext;\n if (primaryLang === 'Swift') {\n mergedContext = mergeSwiftResults(allParseResults.filter((r): r is SwiftParseResult => 'property_wrappers' in r));\n } else if (primaryLang === 'TypeScript' || primaryLang === 'JavaScript') {\n mergedContext = mergeTsResults(allParseResults.filter((r): r is TsParseResult => !('docstrings' in r) && !('property_wrappers' in r) && !('frameworks_used' in r)));\n } else if (primaryLang === 'Python') {\n mergedContext = mergePythonResults(allParseResults.filter((r): r is PythonParseResult => 'docstrings' in r));\n } else {\n mergedContext = mergeCppResults(allParseResults.filter((r): r is CppParseResult => 'error_handling' in r && !('docstrings' in r) && !('property_wrappers' in r)));\n }\n\n // ─── STEP 2: Keyword Extraction ──────────────────────────────────────────\n log('STEP_2', 'Extracting keywords from AST analysis...');\n\n const astKeywords = extractKeywords(mergedContext);\n log('STEP_2', `Extracted ${astKeywords.length} keywords`);\n\n // ─── STEP 3: Build SDK API Index (simplified — use AST keywords as proxy) ──\n log('STEP_3', 'Building SDK API index...');\n\n const sdkApiIndex = {\n sdk_apis: astKeywords.map(kw => ({\n name: kw.keyword,\n kind: kw.source,\n used_in_demo: true,\n })),\n };\n\n // ─── STEP 4: LLM Project Graph Generation ────────────────────────────────\n log('STEP_4', 'Generating project graph via LLM (C0: Scaffold, C1: Overview, C2: Steps)...');\n\n // C0: Scaffold (F0) — uses file list (names only, not content)\n log('STEP_4_C0', 'Extracting FOUNDATION & SETUP feature (F0)...');\n const scaffoldFeature = await extractScaffold({\n goal,\n techStack,\n fileList: filePaths,\n llmConfig,\n sharedClient: client,\n });\n\n // C1: Overview (features meta) — uses already-filtered fileContentsMap\n log('STEP_4_C1', 'Extracting project overview (features meta)...');\n const overview = await extractProjectOverview({\n goal,\n techStack,\n sdkApiIndex,\n fileContentsMap,\n astKeywords,\n llmConfig,\n sharedClient: client,\n });\n\n // Build PBL step (Design Thinking)\n const product = overview.product as Record<string, unknown> | undefined;\n const pblStep: Feature['steps'] extends (infer T)[] ? T : never = {\n id: 'F0-S1',\n sequence: 1,\n name: 'Frame the problem & understand user needs (Design Thinking)',\n description: 'BEFORE CODING — frame the problem and understand what the user needs',\n files: [],\n api_usage: [],\n keywords: ['Design Thinking', 'User Needs', 'Problem Statement', 'User Journey', 'PBL'],\n completion_level: 'base',\n platform: 'app',\n intent: 'Understand user needs and frame problem before writing code',\n outcome: { user_visible: 'Defined problem statement', technical: 'Problem frame context' },\n acceptance: ['Problem statement is clear', 'Primary users identified'],\n requirement_ids: [],\n concept_codes: [],\n effort: { estimated_minutes: 15, complexity: 'low' },\n };\n\n // Merge scaffold F0 with PBL step\n let featuresFull: Feature[] = [];\n if (scaffoldFeature) {\n const scaffoldSteps = [pblStep, ...(scaffoldFeature.steps || [])].map((s, i) => ({\n ...s,\n id: `F0-S${i + 1}`,\n sequence: i + 1,\n }));\n featuresFull.push({\n ...scaffoldFeature,\n id: 'F0',\n name: 'FOUNDATION & SETUP',\n steps: scaffoldSteps,\n });\n } else {\n featuresFull.push({\n id: 'F0',\n name: 'FOUNDATION & SETUP',\n description: 'Frame the problem, get familiar with the tools',\n steps: [pblStep],\n } as Feature);\n }\n\n // Add features from overview\n const overviewFeatures = (product?.features || []) as Feature[];\n featuresFull = [...featuresFull, ...overviewFeatures];\n\n // C2: Extract steps per feature\n log('STEP_4_C2', `Extracting steps for ${overviewFeatures.length} features...`);\n\n const nonF0Features = overviewFeatures.filter(f => f.id !== 'F0');\n if (nonF0Features.length > 0) {\n try {\n const batchedSteps = await extractFeatureStepsBatched(\n goal, techStack, sdkApiIndex, fileContentsMap, nonF0Features, llmConfig, client,\n );\n for (const feature of nonF0Features) {\n const steps = batchedSteps.get(feature.id || '');\n if (steps) feature.steps = steps;\n }\n } catch (err) {\n log('STEP_4_C2', `Batch extraction failed (${err}), falling back to per-feature...`);\n for (const feature of nonF0Features) {\n try {\n const steps = await extractFeatureSteps({\n goal, techStack, sdkApiIndex, fileContentsMap, feature,\n llmConfig,\n sharedClient: client,\n });\n feature.steps = steps;\n } catch (e) {\n log('STEP_4_C2', `Failed for ${feature.id}: ${e}`);\n }\n }\n }\n }\n\n // Build project graph\n const projectGraph: ProjectGraph = {\n schema_version: 3,\n project: {\n id: (overview.project as Record<string, unknown>)?.name?.toString().toLowerCase().replace(/\\s+/g, '-') || 'project',\n name: (overview.project as Record<string, unknown>)?.name?.toString() || 'Project',\n purpose: goal,\n version: '0.1.0',\n project_type: 'app',\n platform: ((overview.project as Record<string, unknown>)?.platforms as string[]) || ['ios'],\n tech_stack: techStack.split(',').reduce((acc, t) => {\n const key = t.trim().toLowerCase();\n if (key) acc[key] = [t.trim()];\n return acc;\n }, {} as Record<string, string[]>),\n architecture: (overview.architecture as Record<string, unknown>)?.layers as string[] || [],\n },\n product: {\n goals: (product?.goals as Array<{ id: string; description: string }>) || [],\n users: (product?.users as Array<{ id: string; goals: string[] }>) || [],\n journeys: (product?.user_journeys as Array<{ id: string; name: string; requirement_ids: string[]; steps: string[]; feature_ids: string[] }>) || [],\n requirements: [],\n development_stages: (product?.development_stages as Array<{ stage: string; product_state: string; need: string[]; learn: string[]; validation: string; cross_feature_value: string; temporary_approach: string }>) || [],\n purpose: String(product?.purpose || ''),\n problem_statement: String(product?.problem_statement || ''),\n primary_users: (product?.primary_users as string[]) || [],\n },\n features: featuresFull,\n capabilities: [],\n implementation: {\n tasks: [],\n },\n missing_gaps: [],\n tech_debt: [],\n };\n\n // ─── STEP 5: Verification ────────────────────────────────────────────────\n log('STEP_5', 'Verifying project graph against source code...');\n\n const { graph: verifiedGraph, hallucinations } = verifyProjectGraph(projectGraph, {\n repoDir,\n sdkApiIndex,\n fileContentsMap,\n });\n log('STEP_5', `Verification complete: ${hallucinations.length} hallucinations found`);\n\n // ─── STEP 6: Concept Escalation ──────────────────────────────────────────\n log('STEP_6', 'Escalating keywords to neutral concepts...');\n\n const featureConcepts = await escalateAndMapConcepts({\n projectGraph: verifiedGraph,\n fileContentsMap,\n llmConfig,\n sharedClient: client,\n });\n log('STEP_6', `Concept mapping complete: ${featureConcepts.size} features mapped`);\n\n // Propagate concept_codes back into verified graph steps\n for (const feature of verifiedGraph.features || []) {\n const fid = feature.id || '';\n const fConcepts = featureConcepts.get(fid) || [];\n for (const step of feature.steps || []) {\n const stepConcepts = fConcepts\n .filter(cm => {\n // Match concept to step: check if step contains the keyword\n const stepKws = [...(step.keywords || []), ...(step.api_usage || [])];\n return stepKws.some(k => k === cm.keyword);\n })\n .map(cm => cm.concept_code);\n // Merge with any existing concept_codes from LLM\n const existing = step.concept_codes || [];\n step.concept_codes = [...new Set([...existing, ...stepConcepts])];\n }\n }\n\n // ─── STEP 7: Concept Resolution ──────────────────────────────────────────\n log('STEP_7', 'Resolving keywords to Master Tree concepts...');\n\n // Collect LLM-generated keywords from verified graph (not just AST)\n const llmKeywords: Keyword[] = [];\n const seenKw = new Set<string>();\n for (const feature of verifiedGraph.features || []) {\n for (const step of feature.steps || []) {\n for (const kw of [...(step.keywords || []), ...(step.api_usage || [])]) {\n if (!seenKw.has(kw.toLowerCase())) {\n seenKw.add(kw.toLowerCase());\n llmKeywords.push({ keyword: kw, source: 'llm_step', platform: 'app', weight: 1.0, context: 'LLM-generated step keyword' });\n }\n }\n }\n }\n // Merge with AST keywords (AST takes precedence for source/weight)\n const astKwMap = new Map(astKeywords.map(k => [k.keyword.toLowerCase(), k]));\n const mergedKeywords: Keyword[] = [];\n const mergedSeen = new Set<string>();\n for (const kw of [...astKeywords, ...llmKeywords]) {\n const key = kw.keyword.toLowerCase();\n if (!mergedSeen.has(key)) {\n mergedSeen.add(key);\n mergedKeywords.push(astKwMap.get(key) || kw);\n }\n }\n\n // Build depth overrides from concept escalation\n const depthOverrides = new Map<string, 'ulo' | 'cio' | 'sio'>();\n for (const mappings of featureConcepts.values()) {\n for (const cm of mappings) {\n if (!depthOverrides.has(cm.keyword)) {\n depthOverrides.set(cm.keyword, cm.depth);\n }\n }\n }\n\n const resolvedConcepts = await resolveConcepts({\n keywords: mergedKeywords,\n goal,\n embeddings,\n depthOverrides,\n llmConfig,\n });\n log('STEP_7', `Resolved: ${resolvedConcepts.summary.resolved_count}, Proposed: ${resolvedConcepts.summary.proposed_count} (${resolvedConcepts.summary.search_mode})`);\n\n // ─── STEP 8: Assembly ────────────────────────────────────────────────────\n log('STEP_8', 'Assembling roadmap with keyword tracking...');\n\n const roadmap = assembleRoadmap({\n projectGraph: verifiedGraph,\n featureConcepts,\n sessionMinutes: 90,\n overheadFactor: 1.15,\n maxMilestoneMinutes: 120,\n });\n log('STEP_8', `Roadmap assembled: ${roadmap.phases.length} phases, ${roadmap.phases.reduce((s, p) => s + p.milestones.length, 0)} milestones`);\n\n return {\n projectGraph: verifiedGraph,\n resolvedConcepts,\n roadmap,\n hallucinations,\n keywords: astKeywords,\n featureConcepts,\n provenance: client.callLog,\n };\n}\n","/**\n * Knowledge Graph Pipeline Orchestrator.\n *\n * Runs: Syllabus Parsing -> Knowledge Graph Generation -> Verification -> CurriculumFeed v2 Emission.\n */\n\nimport { generateKnowledgeGraph, type KnowledgeGraphPipelineOptions } from '../graph/knowledgeGraphPipeline';\nimport { parseSyllabus, type ParsedSyllabus } from '../parsers/syllabusParser';\nimport { emitCurriculumFeed } from '../feed/curriculumFeedEmitter';\nimport type { KnowledgeGraph } from '../schemas/knowledgeGraphSchema';\nimport type { CurriculumFeed } from '../schemas/curriculumFeedSchema';\nimport type { KnowledgeGraphVerificationReport } from '../graph/knowledgeGraphVerifier';\nimport { summarizeProvenance } from '../utils/llmClient';\n\nexport interface KnowledgePipelineOptions extends KnowledgeGraphPipelineOptions {}\n\nexport interface KnowledgePipelineResult {\n knowledgeGraph: KnowledgeGraph;\n parsedSyllabus?: ParsedSyllabus;\n curriculumFeed: CurriculumFeed;\n verificationReport?: KnowledgeGraphVerificationReport;\n warnings: string[];\n}\n\n/**\n * Run the full concept-driven knowledge graph pipeline.\n */\nexport async function runKnowledgeGraphPipeline(\n options: KnowledgePipelineOptions,\n): Promise<KnowledgePipelineResult> {\n const warnings: string[] = [];\n let parsedSyllabus = options.parsedSyllabus;\n\n if (!parsedSyllabus && options.syllabusText) {\n parsedSyllabus = parseSyllabus(options.syllabusText);\n }\n\n const effectiveSubject = options.subject || parsedSyllabus?.subject.title || 'Untitled Subject';\n const effectiveDomain = options.domain || parsedSyllabus?.subject.domain || 'other';\n const effectiveGradeBand = options.gradeBand || parsedSyllabus?.subject.gradeBand;\n const effectiveDesc = options.description || parsedSyllabus?.subject.description;\n\n const result = await generateKnowledgeGraph({\n ...options,\n subject: effectiveSubject,\n domain: effectiveDomain,\n gradeBand: effectiveGradeBand,\n description: effectiveDesc,\n parsedSyllabus,\n });\n\n warnings.push(...result.warnings);\n\n // Emit normalized CurriculumFeed v2\n const curriculumFeed = emitCurriculumFeed(result.knowledgeGraph, {\n warnings,\n provenance: summarizeProvenance(result.provenance),\n });\n\n return {\n knowledgeGraph: result.knowledgeGraph,\n parsedSyllabus,\n curriculumFeed,\n verificationReport: result.verificationReport,\n warnings,\n };\n}\n","/**\n * Hybrid Graph Pipeline Orchestrator.\n *\n * Runs: Hybrid Graph Generation -> CurriculumFeed v2 Emission.\n */\n\nimport { generateHybridGraph, type HybridGraphPipelineOptions } from '../graph/hybridGraphPipeline';\nimport { emitCurriculumFeed } from '../feed/curriculumFeedEmitter';\nimport type { HybridGraph } from '../schemas/hybridGraphSchema';\nimport { summarizeProvenance } from '../utils/llmClient';\nimport type { CurriculumFeed } from '../schemas/curriculumFeedSchema';\n\nexport interface HybridPipelineOptions extends HybridGraphPipelineOptions {}\n\nexport interface HybridPipelineResult {\n hybridGraph: HybridGraph;\n curriculumFeed: CurriculumFeed;\n warnings: string[];\n}\n\n/**\n * Run the hybrid graph generation and feed emission pipeline.\n */\nexport async function runHybridGraphPipeline(\n options: HybridPipelineOptions,\n): Promise<HybridPipelineResult> {\n const warnings: string[] = [];\n const result = await generateHybridGraph(options);\n warnings.push(...result.warnings);\n\n const curriculumFeed = emitCurriculumFeed(result.hybridGraph, {\n warnings,\n provenance: summarizeProvenance(result.provenance),\n });\n\n return {\n hybridGraph: result.hybridGraph,\n curriculumFeed,\n warnings,\n };\n}\n","/**\n * Unified Domain Pipeline Router.\n *\n * Implements the 3-Layer Architecture from docs/ideas/2026-08-30-domain-detection-and-graph-types.md:\n * Layer 1: DOMAIN DETECTION (detectDomainProfile)\n * Layer 2: GRAPH ROUTER (routeDomain)\n * Layer 3: GRAPH GENERATION (runProjectGraphPipeline | runKnowledgeGraphPipeline | runHybridGraphPipeline)\n * Layer 4: NORMALIZED OUTPUT (CurriculumFeed v2)\n */\n\nimport { detectDomainProfile, type DetectDomainProfileOptions } from '../detector/domainProfileDetector';\nimport type { DomainProfile, GraphType } from '../schemas/domainProfileSchema';\nimport type { CurriculumFeed } from '../schemas/curriculumFeedSchema';\nimport { runProjectGraphPipeline, type PipelineOptions, type PipelineResult } from './projectGraphPipeline';\nimport { runKnowledgeGraphPipeline, type KnowledgePipelineOptions, type KnowledgePipelineResult } from './knowledgeGraphPipeline';\nimport { runHybridGraphPipeline, type HybridPipelineOptions, type HybridPipelineResult } from './hybridGraphPipeline';\nimport type { LlmClientConfig } from '../utils/llmClient';\nimport { summarizeProvenance, type LlmCallRecord } from '../utils/llmClient';\nimport { emitCurriculumFeed } from '../feed/curriculumFeedEmitter';\nimport type { ParsedSyllabus } from '../parsers/syllabusParser';\n\nexport interface DomainPipelineOptions extends DetectDomainProfileOptions {\n subject?: string;\n llmConfig?: LlmClientConfig;\n onProgress?: (step: string, message: string) => void;\n parsedSyllabus?: ParsedSyllabus;\n knowledgeTreePath?: string;\n proposalsPath?: string;\n embeddings?: Record<string, { embedding?: number[]; name?: string; description?: string; keywords?: string }>;\n /** Override automatic learning mode detection */\n forcedLearningMode?: 'product' | 'concept' | 'hybrid';\n}\n\nexport interface DomainPipelineResult {\n domainProfile: DomainProfile;\n graphType: GraphType;\n curriculumFeed: CurriculumFeed;\n projectResult?: PipelineResult;\n knowledgeResult?: KnowledgePipelineResult;\n hybridResult?: HybridPipelineResult;\n warnings: string[];\n /** Present only when the AUTO-detected learning mode could not run and the router ran a weaker pipeline instead. An explicit forcedLearningMode request fails closed instead of downgrading. */\n modeDowngrade?: { from: GraphType; to: GraphType; reason: string };\n}\n\n/**\n * Route and execute the appropriate domain pipeline based on input context.\n */\nexport async function runDomainPipeline(\n options: DomainPipelineOptions,\n): Promise<DomainPipelineResult> {\n const warnings: string[] = [];\n const log = (step: string, msg: string) => {\n console.log(`[ROUTER-${step}] ${msg}`);\n options.onProgress?.(step, msg);\n };\n\n // ─── Layer 1: Domain Detection ───────────────────────────────────────────\n log('LAYER_1', 'Detecting domain profile...');\n const domainProfile = detectDomainProfile(options);\n\n const effectiveMode = options.forcedLearningMode || domainProfile.learningMode;\n log('LAYER_2', `Routing to pipeline for learning mode: ${effectiveMode} (graphType: ${domainProfile.graphType})`);\n\n // ─── Layer 3: Dispatch & Execute ─────────────────────────────────────────\n if (effectiveMode === 'concept') {\n log('LAYER_3', 'Executing Knowledge Graph Pipeline (Concept-driven)...');\n const knowledgeResult = await runKnowledgeGraphPipeline({\n subject: options.subject || domainProfile.detectedSubject || options.goal || options.description || 'General Subject',\n description: options.description,\n syllabusText: options.syllabusText,\n parsedSyllabus: options.parsedSyllabus,\n gradeBand: options.gradeBand,\n domain: domainProfile.domainCategory,\n techStack: options.techStack || domainProfile.detectedTechStack?.[0],\n llmConfig: options.llmConfig,\n onProgress: options.onProgress,\n knowledgeTreePath: options.knowledgeTreePath,\n proposalsPath: options.proposalsPath,\n });\n warnings.push(...knowledgeResult.warnings);\n\n return {\n domainProfile,\n graphType: 'knowledge_graph',\n curriculumFeed: knowledgeResult.curriculumFeed,\n knowledgeResult,\n warnings,\n };\n }\n\n if (effectiveMode === 'hybrid') {\n log('LAYER_3', 'Executing Hybrid Graph Pipeline...');\n if (!options.repoDir && options.forcedLearningMode === 'hybrid') {\n throw new Error('forcedLearningMode \"hybrid\" requires repoDir — refusing to silently degrade to a concept-only feed (fail-closed)');\n }\n if (options.repoDir) {\n const projectResult = await runProjectGraphPipeline({\n repoDir: options.repoDir,\n goal: options.goal || 'Build complete project',\n techStack: options.techStack || 'typescript',\n llmConfig: options.llmConfig,\n embeddings: options.embeddings,\n onProgress: options.onProgress,\n });\n\n const knowledgeResult = await runKnowledgeGraphPipeline({\n subject: options.subject || domainProfile.detectedSubject || options.goal || 'Subject Theory',\n description: options.description,\n syllabusText: options.syllabusText,\n parsedSyllabus: options.parsedSyllabus,\n domain: domainProfile.domainCategory,\n techStack: options.techStack,\n llmConfig: options.llmConfig,\n onProgress: options.onProgress,\n knowledgeTreePath: options.knowledgeTreePath,\n proposalsPath: options.proposalsPath,\n });\n\n const hybridResult = await runHybridGraphPipeline({\n projectGraph: projectResult.projectGraph,\n knowledgeGraph: knowledgeResult.knowledgeGraph,\n llmConfig: options.llmConfig,\n onProgress: options.onProgress,\n });\n\n warnings.push(...hybridResult.warnings);\n return {\n domainProfile,\n graphType: 'hybrid_graph',\n curriculumFeed: hybridResult.curriculumFeed,\n projectResult,\n knowledgeResult,\n hybridResult,\n warnings,\n };\n } else {\n const downgradeReason = 'Hybrid learning mode requested but repoDir was not provided — falling back to concept-driven knowledge graph pipeline';\n warnings.push(downgradeReason);\n const knowledgeResult = await runKnowledgeGraphPipeline({\n subject: options.subject || domainProfile.detectedSubject || options.goal || 'Subject Theory',\n description: options.description,\n syllabusText: options.syllabusText,\n parsedSyllabus: options.parsedSyllabus,\n domain: domainProfile.domainCategory,\n techStack: options.techStack,\n llmConfig: options.llmConfig,\n onProgress: options.onProgress,\n knowledgeTreePath: options.knowledgeTreePath,\n proposalsPath: options.proposalsPath,\n });\n warnings.push(...knowledgeResult.warnings);\n\n return {\n domainProfile,\n graphType: 'knowledge_graph',\n curriculumFeed: knowledgeResult.curriculumFeed,\n knowledgeResult,\n warnings,\n modeDowngrade: { from: 'hybrid_graph', to: 'knowledge_graph', reason: downgradeReason },\n };\n }\n }\n\n // Default: product-driven\n log('LAYER_3', 'Executing Project Graph Pipeline (Product-driven)...');\n if (!options.repoDir) {\n throw new Error('repoDir is required for product-driven project graph pipeline');\n }\n\n const projectResult = await runProjectGraphPipeline({\n repoDir: options.repoDir,\n goal: options.goal || 'Build complete project',\n techStack: options.techStack || domainProfile.detectedTechStack?.[0] || 'typescript',\n llmConfig: options.llmConfig,\n embeddings: options.embeddings,\n onProgress: options.onProgress,\n });\n\n // Emit curriculum feed from project graph (static import: feed/ depends only on\n // schemas/, so there is no cycle to dodge — the dynamic import was pure inconsistency)\n const curriculumFeed = emitCurriculumFeed(projectResult.projectGraph, {\n warnings,\n hallucinationCount: projectResult.hallucinations.length,\n provenance: summarizeProvenance(projectResult.provenance),\n });\n\n return {\n domainProfile,\n graphType: 'project_graph',\n curriculumFeed,\n projectResult,\n warnings,\n };\n}\n"]}
@@ -1,3 +1,5 @@
1
+ import { stripDiacritics } from './chunk-OYSZQVPY.mjs';
2
+
1
3
  // src/detector/inputTypeDetector.ts
2
4
  var CODE_EXTENSIONS = /* @__PURE__ */ new Set([
3
5
  ".swift",
@@ -572,6 +574,9 @@ function detectSyllabusLanguage(text) {
572
574
  }
573
575
  return "en";
574
576
  }
577
+ function normalizeText(s) {
578
+ return s.normalize("NFC").toLowerCase();
579
+ }
575
580
  function detectDomain(options) {
576
581
  const evidence = [];
577
582
  const detectedTechStack = [];
@@ -628,15 +633,19 @@ function detectDomain(options) {
628
633
  }
629
634
  }
630
635
  }
631
- const textContent = [
636
+ const textContent = normalizeText([
632
637
  options.description || "",
633
638
  options.goal || "",
634
639
  options.syllabusText || ""
635
- ].join(" ").toLowerCase();
640
+ ].join(" "));
641
+ const textNoMarks = stripDiacritics(textContent);
636
642
  for (const [domain, keywords] of Object.entries(DOMAIN_KEYWORDS)) {
637
643
  const cat = domain;
638
644
  for (const kw of keywords) {
639
- if (textContent.includes(kw.toLowerCase())) {
645
+ const kwNorm = normalizeText(kw);
646
+ const kwPlain = stripDiacritics(kw);
647
+ const matched = textContent.includes(kwNorm) || kwPlain !== kwNorm && textNoMarks.includes(kwPlain);
648
+ if (matched) {
640
649
  scores[cat] += 0.1;
641
650
  if (!evidence.some((e) => e.includes(`"${kw}"`))) {
642
651
  evidence.push(`Keyword "${kw}" \u2192 ${cat}`);
@@ -675,11 +684,12 @@ function detectDomain(options) {
675
684
  }
676
685
  if (options.syllabusText) {
677
686
  const syllabusLang = detectSyllabusLanguage(options.syllabusText);
678
- const syllabusLower = options.syllabusText.toLowerCase();
679
- if (syllabusLower.includes("h\xECnh h\u1ECDc") || syllabusLower.includes("\u0111\u1EA1i s\u1ED1") || syllabusLower.includes("geometry") || syllabusLower.includes("algebra") || syllabusLower.includes("\u51E0\u4F55") || syllabusLower.includes("\u4EE3\u6570") || syllabusLower.includes("\u5E7E\u4F55") || syllabusLower.includes("\u4EE3\u6570") || syllabusLower.includes("g\xE9om\xE9trie") || syllabusLower.includes("alg\xE8bre")) {
687
+ const syllabusLower = normalizeText(options.syllabusText);
688
+ const syllabusPlain = stripDiacritics(options.syllabusText);
689
+ if (syllabusLower.includes("h\xECnh h\u1ECDc") || syllabusLower.includes("\u0111\u1EA1i s\u1ED1") || syllabusPlain.includes("hinh hoc") || syllabusPlain.includes("dai so") || syllabusLower.includes("geometry") || syllabusLower.includes("algebra") || syllabusLower.includes("\u51E0\u4F55") || syllabusLower.includes("\u4EE3\u6570") || syllabusLower.includes("\u5E7E\u4F55") || syllabusLower.includes("\u4EE3\u6570") || syllabusLower.includes("g\xE9om\xE9trie") || syllabusLower.includes("alg\xE8bre")) {
680
690
  scores.math += 0.5;
681
691
  detectedSubject = "Mathematics";
682
- } else if (syllabusLower.includes("v\u1EADt l\xFD") || syllabusLower.includes("h\xF3a") || syllabusLower.includes("sinh") || syllabusLower.includes("physics") || syllabusLower.includes("chemistry") || syllabusLower.includes("biology") || syllabusLower.includes("\u7269\u7406") || syllabusLower.includes("\u5316\u5B66") || syllabusLower.includes("\u7269\u7406") || syllabusLower.includes("\u5316\u5B66") || syllabusLower.includes("physique") || syllabusLower.includes("chimie")) {
692
+ } else if (syllabusLower.includes("v\u1EADt l\xFD") || syllabusLower.includes("h\xF3a") || syllabusPlain.includes("vat ly") || syllabusPlain.includes("hoa") || syllabusLower.includes("sinh") || syllabusLower.includes("physics") || syllabusLower.includes("chemistry") || syllabusLower.includes("biology") || syllabusLower.includes("\u7269\u7406") || syllabusLower.includes("\u5316\u5B66") || syllabusLower.includes("\u7269\u7406") || syllabusLower.includes("\u5316\u5B66") || syllabusLower.includes("physique") || syllabusLower.includes("chimie")) {
683
693
  scores.science += 0.5;
684
694
  detectedSubject = "Natural Science";
685
695
  } else if (syllabusLower.includes("ti\u1EBFng anh") || syllabusLower.includes("english") || syllabusLower.includes("grammar") || syllabusLower.includes("\u82F1\u8BED") || syllabusLower.includes("\u82F1\u8A9E") || syllabusLower.includes("anglais")) {
@@ -884,5 +894,5 @@ function determineGraphType(learningMode) {
884
894
  }
885
895
 
886
896
  export { detectDomain, detectDomainProfile, detectInputType, detectLearningMode };
887
- //# sourceMappingURL=chunk-BL5NBKPH.mjs.map
888
- //# sourceMappingURL=chunk-BL5NBKPH.mjs.map
897
+ //# sourceMappingURL=chunk-67GXK3ZE.mjs.map
898
+ //# sourceMappingURL=chunk-67GXK3ZE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/detector/inputTypeDetector.ts","../src/detector/domainDetector.ts","../src/detector/learningModeDetector.ts","../src/detector/domainProfileDetector.ts"],"names":["raw"],"mappings":"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","file":"chunk-67GXK3ZE.mjs","sourcesContent":["/**\n * Input Type Detection — determines what kind of input the user provided.\n *\n * Signals:\n * repository: repoUrl, repoDir, or source code files present\n * syllabus: syllabusText, chapters[], or curriculum-like structure\n * files: non-code files (3D models, images, documents)\n * description: free-text description (>100 chars)\n * mixed: combination of the above\n */\n\nimport type { InputType } from '../schemas/domainProfileSchema';\n\nexport interface InputTypeDetectionResult {\n inputType: InputType;\n confidence: number;\n evidence: string[];\n}\n\nexport interface DetectInputTypeOptions {\n repoUrl?: string;\n repoDir?: string;\n description?: string;\n syllabusText?: string;\n chapters?: string[];\n fileExtensions?: string[];\n goal?: string;\n}\n\nconst CODE_EXTENSIONS = new Set([\n '.swift', '.ts', '.tsx', '.js', '.jsx', '.py', '.ino', '.cpp', '.c', '.h', '.hpp',\n '.kt', '.kts', '.java', '.cs', '.rb', '.go', '.rs', '.php', '.lua', '.r', '.m',\n]);\n\nconst NON_CODE_EXTENSIONS = new Set([\n '.stl', '.obj', '.step', '.stp', '.iges', '.igs', // 3D models\n '.png', '.jpg', '.jpeg', '.gif', '.svg', '.bmp', // Images\n '.pdf', '.doc', '.docx', '.pptx', '.xlsx', // Documents\n '.tc3', '.f3d', // CAD files\n '.mp3', '.wav', '.midi', // Audio\n '.mp4', '.avi', '.mov', // Video\n]);\n\n/**\n * Detect input type from user-provided options.\n */\nexport function detectInputType(options: DetectInputTypeOptions): InputTypeDetectionResult {\n const evidence: string[] = [];\n let repoScore = 0;\n let syllabusScore = 0;\n let filesScore = 0;\n let descriptionScore = 0;\n\n // Check for repository signals\n if (options.repoUrl) {\n repoScore += 0.5;\n evidence.push(`repoUrl provided: ${options.repoUrl}`);\n }\n if (options.repoDir) {\n repoScore += 0.5;\n evidence.push(`repoDir provided: ${options.repoDir}`);\n }\n\n // Check for syllabus signals\n if (options.syllabusText && options.syllabusText.length > 50) {\n syllabusScore += 0.6;\n evidence.push(`syllabusText provided (${options.syllabusText.length} chars)`);\n }\n if (options.chapters && options.chapters.length > 0) {\n syllabusScore += 0.4;\n evidence.push(`${options.chapters.length} chapters provided`);\n }\n\n // Check for file signals\n if (options.fileExtensions && options.fileExtensions.length > 0) {\n const codeCount = options.fileExtensions.filter(ext => CODE_EXTENSIONS.has(ext)).length;\n const nonCodeCount = options.fileExtensions.filter(ext => NON_CODE_EXTENSIONS.has(ext)).length;\n\n if (nonCodeCount > 0) {\n filesScore += 0.7;\n evidence.push(`${nonCodeCount} non-code files detected: ${options.fileExtensions.filter(ext => NON_CODE_EXTENSIONS.has(ext)).join(', ')}`);\n }\n if (codeCount > 0 && repoScore === 0) {\n repoScore += 0.3;\n evidence.push(`${codeCount} source code files detected`);\n }\n }\n\n // Check for description signals\n if (options.description && options.description.length > 100) {\n descriptionScore += 0.5;\n evidence.push(`description provided (${options.description.length} chars)`);\n }\n if (options.goal && options.goal.length > 20) {\n descriptionScore += 0.3;\n evidence.push(`goal provided (${options.goal.length} chars)`);\n }\n\n // Determine winner\n const scores = [\n { type: 'repository' as InputType, score: repoScore },\n { type: 'syllabus' as InputType, score: syllabusScore },\n { type: 'files' as InputType, score: filesScore },\n { type: 'description' as InputType, score: descriptionScore },\n ];\n\n scores.sort((a, b) => b.score - a.score);\n const winner = scores[0];\n\n // Check for mixed\n const activeTypes = scores.filter(s => s.score >= 0.3);\n if (activeTypes.length >= 2) {\n return {\n inputType: 'mixed',\n confidence: 0.7,\n evidence: [...evidence, `Mixed input detected: ${activeTypes.map(t => t.type).join(' + ')}`],\n };\n }\n\n if (winner.score === 0) {\n return {\n inputType: 'description',\n confidence: 0.3,\n evidence: [...evidence, 'No strong signals — defaulting to description'],\n };\n }\n\n return {\n inputType: winner.type,\n confidence: Math.min(winner.score, 1.0),\n evidence,\n };\n}\n","/**\n * Domain Category Detection — determines the subject domain from context.\n *\n * Uses multi-signal scoring:\n * - File extensions (code vs non-code, context-dependent)\n * - Keywords in description/goal (multi-language)\n * - Tech stack mentions\n * - Subject-specific vocabulary\n * - Disambiguation for overlapping domains (e.g., .cpp in software vs hardware)\n */\n\nimport type { DomainCategory } from '../schemas/domainProfileSchema';\nimport { stripDiacritics } from '../utils/diacritics';\n\nexport interface DomainDetectionResult {\n domainCategory: DomainCategory;\n confidence: number;\n evidence: string[];\n detectedTechStack: string[];\n detectedSubject: string;\n ambiguous?: { domain1: DomainCategory; domain2: DomainCategory; reason: string };\n}\n\nexport interface DetectDomainOptions {\n description?: string;\n goal?: string;\n syllabusText?: string;\n techStack?: string;\n fileExtensions?: string[];\n repoUrl?: string;\n}\n\n\n\n\n// ─── Keyword lists per domain (broad matching) ──────────────────────────────\nconst DOMAIN_KEYWORDS: Record<DomainCategory, string[]> = {\n software: [\n 'app', 'web', 'api', 'database', 'frontend', 'backend', 'mobile',\n 'swift', 'react', 'vue', 'angular', 'node', 'python', 'java',\n 'typescript', 'javascript', 'html', 'css', 'sql', 'rest', 'graphql',\n 'git', 'docker', 'kubernetes', 'ci/cd', 'deploy',\n 'swiftui', 'uikit', 'flutter', 'kotlin', 'android', 'ios',\n 'nextjs', 'nuxt', 'svelte', 'django', 'flask', 'express',\n ],\n hardware_iot: [\n 'arduino', 'robot', 'sensor', 'motor', 'esp32', 'gpio',\n 'raspberry pi', 'iot', 'firmware', 'embedded', 'microcontroller',\n 'led', 'servo', 'potentiometer', 'breadboard', 'soldering',\n 'i2c', 'spi', 'pwm', 'uart', 'analog', 'digital',\n 'ultrasonic', 'infrared', 'bluetooth', 'wifi module',\n 'pin', 'voltage', 'resistor', 'capacitor', 'circuit',\n ],\n '3d_design': [\n 'tinkercad', '3d model', 'cad', 'parametric', 'stl', 'obj',\n 'fusion360', 'blender', 'solidworks', 'autocad', 'freecad',\n 'shape', 'dimension', 'extrude', 'revolve', 'fillet', 'chamfer',\n 'assembly', 'constraint', 'sketch', 'plane', 'axis',\n 'render', 'mesh', 'nurbs', 'surface', 'volume',\n ],\n math: [\n // Vietnamese\n 'hình học', 'đại số', 'giải tích', 'xác suất', 'thống kê',\n 'tam giác', 'đường tròn', 'phương trình', 'bất phương trình',\n 'số học', 'tổ hợp', 'hoán vị', 'độ đo', 'góc', 'cạnh',\n 'diện tích', 'thể tích', 'chu vi', 'đường cao', 'trung tuyến',\n // English\n 'geometry', 'algebra', 'calculus', 'trigonometry', 'logarithm',\n 'probability', 'statistics', 'derivative', 'integral', 'matrix',\n 'vector', 'theorem', 'proof', 'angle', 'perimeter', 'area',\n // Chinese\n '几何', '代数', '微积分', '概率', '统计', '三角形', '圆', '方程',\n // Japanese\n '幾何', '代数', '微分', '積分', '確率', '統計',\n // French\n 'géométrie', 'algèbre', 'calcul', 'trigonométrie', 'probabilité',\n ],\n science: [\n // Vietnamese\n 'lý thuyết', 'nguyên lý', 'thí nghiệm', 'điện', 'lực',\n 'hóa học', 'sinh học', 'vật lý', 'địa lý',\n 'phản ứng', 'nguyên tố', 'phân tử',\n 'năng lượng', 'cảm ứng', 'từ trường', 'quang học',\n 'môi trường', 'sinh thái',\n // English\n 'physics', 'chemistry', 'biology', 'earth science',\n 'cell', 'gene', 'evolution', 'ecosystem', 'molecule', 'atom',\n // Chinese\n '物理', '化学', '生物', '地理',\n // Japanese\n '物理', '化学', '生物',\n // French\n 'physique', 'chimie', 'biologie',\n ],\n language: [\n // Vietnamese\n 'tiếng anh', 'tiếng việt', 'ngữ pháp', 'từ vựng',\n 'đọc', 'viết', 'nói', 'nghe',\n // English\n 'grammar', 'vocabulary', 'writing', 'reading', 'speaking',\n 'listening', 'pronunciation', 'essay', 'paragraph', 'sentence',\n 'verb', 'noun', 'adjective', 'ielts', 'toeic', 'toefl',\n // Chinese\n '英语', '语法', '词汇', '阅读', '写作',\n // Japanese\n '英語', '文法', '語彙', '読解', '作文',\n // French\n 'anglais', 'grammaire', 'vocabulaire', 'lecture', 'écriture',\n ],\n arts: [\n // Vietnamese\n 'âm nhạc', 'nhạc lý', 'solfège', 'đàn', 'piano', 'guitar',\n 'hội họa', 'thiết kế', 'nhiếp ảnh',\n 'tranh', 'màu', 'sáng tác', 'biên khúc',\n // English\n 'music', 'art', 'painting', 'drawing', 'sketch', 'photography',\n 'color theory', 'composition', 'typography', 'layout',\n 'digital art', 'illustration', 'figma',\n // Chinese\n '音乐', '美术', '绘画', '摄影', '设计',\n // Japanese\n '音楽', '美術', '絵画', '写真', 'デザイン',\n // French\n 'musique', 'art', 'peinture', 'dessin', 'photographie',\n ],\n research: [\n // Vietnamese\n 'nghiên cứu', 'thống kê', 'phương pháp luận', 'phân tích dữ liệu',\n 'định tính', 'định lượng', 'giả thuyết',\n 'mẫu', 'tổng thể', 'tương quan', 'hồi quy',\n 'tài liệu tham khảo', 'trích dẫn', 'tóm tắt',\n // English\n 'research', 'survey', 'methodology', 'data analysis',\n 'qualitative', 'quantitative', 'hypothesis', 'experiment',\n 'sample', 'population', 'correlation', 'regression',\n 'literature review', 'citation', 'abstract',\n // Chinese\n '研究', '调查', '方法论', '数据分析',\n // Japanese\n '研究', '調査', '方法論', 'データ分析',\n // French\n 'recherche', 'enquête', 'méthodologie', 'analyse de données',\n ],\n business: [\n // Vietnamese\n 'kinh doanh', 'tài chính', 'quản lý', 'marketing', 'bán hàng',\n 'khởi nghiệp', 'kế hoạch kinh doanh', 'doanh thu', 'lợi nhuận',\n 'quản trị', 'tài khoản', 'đầu tư', 'ngân sách',\n // English\n 'business', 'finance', 'accounting', 'investment', 'budget',\n 'startup', 'revenue', 'profit', 'roi', 'sales',\n 'product management', 'agile', 'scrum', 'kanban',\n // Chinese\n '商业', '金融', '会计', '投资', '营销',\n // Japanese\n 'ビジネス', '金融', '会計', '投資', 'マーケティング',\n // French\n 'affaires', 'finance', 'comptabilité', 'investissement',\n ],\n other: [],\n};\n\n// ─── Extension → Domain mapping (context-dependent for ambiguous extensions) ──\nconst EXTENSION_DOMAIN: Record<string, DomainCategory> = {\n '.swift': 'software',\n '.ts': 'software', '.tsx': 'software',\n '.js': 'software', '.jsx': 'software',\n '.py': 'software',\n '.kt': 'software', '.kts': 'software',\n '.java': 'software', '.cs': 'software',\n '.go': 'software', '.rs': 'software',\n '.rb': 'software', '.php': 'software',\n '.lua': 'software', '.r': 'software',\n // .ino is ALWAYS hardware\n '.ino': 'hardware_iot',\n // .cpp/.c/.h are CONTEXT-DEPENDENT → resolve in detection logic\n '.stl': '3d_design', '.obj': '3d_design',\n '.step': '3d_design', '.stp': '3d_design',\n '.tc3': '3d_design', '.f3d': '3d_design',\n};\n\n// Extensions that need context disambiguation\nconst AMBIGUOUS_EXTENSIONS = new Set(['.cpp', '.c', '.h', '.hpp']);\n\n// ─── Syllabus language detection ─────────────────────────────────────────────\nconst LANG_PATTERNS: Array<{ lang: string; patterns: RegExp[] }> = [\n { lang: 'vi', patterns: [/[ạảãàáạảãạ]/i, /\\bgiải\\b/, /\\btính\\b/] },\n { lang: 'zh', patterns: [/[\\u4e00-\\u9fff]{2,}/] },\n { lang: 'ja', patterns: [/[\\u3040-\\u309f\\u30a0-\\u30ff]{2,}/] },\n { lang: 'ko', patterns: [/[\\uac00-\\ud7af]{2,}/] },\n { lang: 'fr', patterns: [/\\b(la|le|les|des|une|est|sont|avec|pour|dans)\\b/i] },\n];\n\nfunction detectSyllabusLanguage(text: string): string {\n for (const { lang, patterns } of LANG_PATTERNS) {\n if (patterns.some(p => p.test(text))) return lang;\n }\n return 'en';\n}\n\n// ─── Text normalization ───────────────────────────────────────────────────────\n// Vietnamese input reaches us in two Unicode forms. NFC composes \"ộ\" into one code\n// point; NFD (what several input methods and older text sources emit) splits it into\n// \"o\" + U+0312 + U+0300. Measured: one identical sentence classified as `math`\n// (confidence 1.0) in NFC and `other` (confidence 0.2) in NFD, because the keyword\n// table is NFC and the comparison was a raw `includes`. Normalize at the boundary,\n// and compare a diacritic-stripped form too so \"hình học\" matches unaccented input.\n// Stripping is Latin-only: CJK/Kana carry no combining marks and must stay intact.\nfunction normalizeText(s: string): string {\n return s.normalize('NFC').toLowerCase();\n}\n\n// ─── Main Detection Function ─────────────────────────────────────────────────\nexport function detectDomain(options: DetectDomainOptions): DomainDetectionResult {\n const evidence: string[] = [];\n const detectedTechStack: string[] = [];\n let detectedSubject = '';\n let ambiguous: DomainDetectionResult['ambiguous'];\n\n const scores: Record<DomainCategory, number> = {\n software: 0, hardware_iot: 0, '3d_design': 0,\n math: 0, science: 0, language: 0, arts: 0,\n research: 0, business: 0, other: 0,\n };\n\n // ─── 1. File Extension Signals ───────────────────────────────────────────\n const hasHardwareContext = !!(\n options.techStack?.toLowerCase().match(/arduino|esp32|raspberry|embedded|iot/)\n || options.description?.toLowerCase().match(/arduino|robot|sensor|motor|circuit/)\n || options.goal?.toLowerCase().match(/arduino|robot|sensor|motor|circuit/)\n );\n\n const hasSoftwareContext = !!(\n options.techStack?.toLowerCase().match(/swift|react|vue|angular|python|java|typescript|javascript/)\n || options.description?.toLowerCase().match(/app|web|api|frontend|backend|mobile/)\n || options.goal?.toLowerCase().match(/app|web|api|frontend|backend|mobile/)\n );\n\n if (options.fileExtensions) {\n for (const ext of options.fileExtensions) {\n const extLower = ext.toLowerCase();\n\n // Always-hardware extensions\n if (extLower === '.ino') {\n scores.hardware_iot += 0.5;\n evidence.push(`File extension ${ext} → hardware_iot (always)`);\n continue;\n }\n\n // Ambiguous extensions → context-dependent\n if (AMBIGUOUS_EXTENSIONS.has(extLower)) {\n if (hasHardwareContext && !hasSoftwareContext) {\n scores.hardware_iot += 0.3;\n evidence.push(`File extension ${ext} → hardware_iot (hardware context)`);\n } else if (hasSoftwareContext && !hasHardwareContext) {\n scores.software += 0.3;\n evidence.push(`File extension ${ext} → software (software context)`);\n } else if (hasHardwareContext && hasSoftwareContext) {\n // Both contexts → slight preference for software (more common for .cpp)\n scores.software += 0.15;\n scores.hardware_iot += 0.15;\n evidence.push(`File extension ${ext} → ambiguous (both software and hardware context)`);\n ambiguous = {\n domain1: 'software',\n domain2: 'hardware_iot',\n reason: `.cpp/.c/.h files present with both software and hardware context keywords`,\n };\n } else {\n // No context → default to software\n scores.software += 0.2;\n evidence.push(`File extension ${ext} → software (default, no context)`);\n }\n continue;\n }\n\n // Clear mapping extensions\n const domain = EXTENSION_DOMAIN[extLower];\n if (domain) {\n scores[domain] += 0.3;\n evidence.push(`File extension ${ext} → ${domain}`);\n }\n }\n }\n\n // ─── 2. Text Content Signals (multi-language) ─────────────────────────────\n const textContent = normalizeText([\n options.description || '',\n options.goal || '',\n options.syllabusText || '',\n ].join(' '));\n const textNoMarks = stripDiacritics(textContent);\n\n for (const [domain, keywords] of Object.entries(DOMAIN_KEYWORDS)) {\n const cat = domain as DomainCategory;\n for (const kw of keywords) {\n const kwNorm = normalizeText(kw);\n const kwPlain = stripDiacritics(kw);\n // Second form only helps Latin keywords — for CJK the stripped form equals the\n // original, so this degrades to the first check rather than widening the match.\n const matched = textContent.includes(kwNorm)\n || (kwPlain !== kwNorm && textNoMarks.includes(kwPlain));\n if (matched) {\n scores[cat] += 0.1;\n if (!evidence.some(e => e.includes(`\"${kw}\"`))) {\n evidence.push(`Keyword \"${kw}\" → ${cat}`);\n }\n }\n }\n }\n\n // ─── 3. Tech Stack Signals ────────────────────────────────────────────────\n if (options.techStack) {\n const techItems = options.techStack.split(',').map(t => t.trim());\n for (const tech of techItems) {\n const techL = tech.toLowerCase();\n if (['swift', 'swiftui', 'uikit', 'ios'].some(k => techL.includes(k))) {\n scores.software += 0.4;\n detectedTechStack.push(tech);\n } else if (['react', 'vue', 'angular', 'next', 'nuxt', 'typescript', 'javascript'].some(k => techL.includes(k))) {\n scores.software += 0.4;\n detectedTechStack.push(tech);\n } else if (['python', 'django', 'flask'].some(k => techL.includes(k))) {\n scores.software += 0.3;\n detectedTechStack.push(tech);\n } else if (['arduino', 'esp32', 'raspberry'].some(k => techL.includes(k))) {\n scores.hardware_iot += 0.5;\n detectedTechStack.push(tech);\n } else if (['tinkercad', 'fusion360', 'blender'].some(k => techL.includes(k))) {\n scores['3d_design'] += 0.5;\n detectedTechStack.push(tech);\n } else if (['c++', 'c', 'cpp'].some(k => techL === k || techL.endsWith(k))) {\n // C++/C → context-dependent\n if (hasHardwareContext) {\n scores.hardware_iot += 0.3;\n } else {\n scores.software += 0.3;\n }\n detectedTechStack.push(tech);\n }\n }\n }\n\n // ─── 4. Syllabus Content Signals (with language detection) ────────────────\n if (options.syllabusText) {\n const syllabusLang = detectSyllabusLanguage(options.syllabusText);\n const syllabusLower = normalizeText(options.syllabusText);\n const syllabusPlain = stripDiacritics(options.syllabusText);\n\n if (syllabusLower.includes('hình học') || syllabusLower.includes('đại số')\n || syllabusPlain.includes('hinh hoc') || syllabusPlain.includes('dai so')\n || syllabusLower.includes('geometry') || syllabusLower.includes('algebra')\n || syllabusLower.includes('几何') || syllabusLower.includes('代数')\n || syllabusLower.includes('幾何') || syllabusLower.includes('代数')\n || syllabusLower.includes('géométrie') || syllabusLower.includes('algèbre')) {\n scores.math += 0.5;\n detectedSubject = 'Mathematics';\n } else if (syllabusLower.includes('vật lý') || syllabusLower.includes('hóa')\n || syllabusPlain.includes('vat ly') || syllabusPlain.includes('hoa')\n || syllabusLower.includes('sinh') || syllabusLower.includes('physics')\n || syllabusLower.includes('chemistry') || syllabusLower.includes('biology')\n || syllabusLower.includes('物理') || syllabusLower.includes('化学')\n || syllabusLower.includes('物理') || syllabusLower.includes('化学')\n || syllabusLower.includes('physique') || syllabusLower.includes('chimie')) {\n scores.science += 0.5;\n detectedSubject = 'Natural Science';\n } else if (syllabusLower.includes('tiếng anh') || syllabusLower.includes('english')\n || syllabusLower.includes('grammar') || syllabusLower.includes('英语')\n || syllabusLower.includes('英語') || syllabusLower.includes('anglais')) {\n scores.language += 0.5;\n detectedSubject = 'English Language';\n }\n\n evidence.push(`Syllabus language detected: ${syllabusLang}`);\n }\n\n // ─── 5. Scoring & Winner ─────────────────────────────────────────────────\n const entries = Object.entries(scores).filter(([k]) => k !== 'other') as [DomainCategory, number][];\n entries.sort((a, b) => b[1] - a[1]);\n const [winner, winnerScore] = entries[0];\n\n if (winnerScore === 0) {\n return {\n domainCategory: 'other',\n confidence: 0.2,\n evidence: [...evidence, 'No domain signals detected'],\n detectedTechStack,\n detectedSubject,\n };\n }\n\n // Check for near-tie (within 0.15) → ambiguous\n const second = entries[1];\n if (second && (winnerScore - second[1]) < 0.15 && winnerScore > 0) {\n ambiguous = {\n domain1: winner,\n domain2: second[0],\n reason: `Scores very close: ${winner}=${winnerScore.toFixed(2)}, ${second[0]}=${second[1].toFixed(2)}`,\n };\n }\n\n const totalScore = entries.reduce((sum, [, s]) => sum + s, 0);\n const confidence = totalScore > 0 ? Math.min(winnerScore / totalScore + 0.3, 1.0) : 0.3;\n\n return {\n domainCategory: winner,\n confidence,\n evidence: evidence.slice(0, 20),\n detectedTechStack,\n detectedSubject,\n ambiguous,\n };\n}\n","/**\n * Learning Mode Detection — determines product vs concept vs hybrid.\n *\n * Logic:\n * - Repository + build verbs → product\n * - Syllabus + no source code → concept\n * - Repository + understanding verbs → hybrid\n * - Domain category heuristic (math/science → concept, software/hardware → product)\n */\n\nimport type { LearningMode, DomainCategory, InputType } from '../schemas/domainProfileSchema';\n\nexport interface LearningModeDetectionResult {\n learningMode: LearningMode;\n confidence: number;\n evidence: string[];\n}\n\nexport interface DetectLearningModeOptions {\n inputType: InputType;\n domainCategory: DomainCategory;\n goal?: string;\n description?: string;\n hasRepo: boolean;\n hasSyllabus: boolean;\n}\n\n// ─── Verb patterns ───────────────────────────────────────────────────────────\n\nconst BUILD_VERBS = [\n 'build', 'create', 'develop', 'implement', 'construct', 'make',\n 'xây dựng', 'tạo', 'phát triển', 'triển khai', 'lắp ráp',\n 'code', 'program', 'design a', 'set up', 'deploy',\n];\n\nconst UNDERSTAND_VERBS = [\n 'understand', 'learn', 'grasp', 'comprehend', 'master',\n 'hiểu', 'nắm vững', 'học', 'tiếp thu', 'am hiểu',\n 'vận dụng', 'phân tích', 'đánh giá', 'so sánh',\n 'explain', 'describe', 'analyze', 'evaluate', 'compare',\n];\n\nconst CONCEPT_DOMAINS: DomainCategory[] = ['math', 'science', 'language', 'arts', 'research', 'business'];\nconst PRODUCT_DOMAINS: DomainCategory[] = ['software', 'hardware_iot', '3d_design'];\n\n/**\n * Detect learning mode from context.\n */\nexport function detectLearningMode(options: DetectLearningModeOptions): LearningModeDetectionResult {\n const evidence: string[] = [];\n const text = [options.goal || '', options.description || ''].join(' ').toLowerCase();\n\n let productScore = 0;\n let conceptScore = 0;\n\n // 1. Input type signals\n if (options.hasRepo) {\n productScore += 0.3;\n evidence.push('Repository present → product signal');\n }\n if (options.hasSyllabus) {\n conceptScore += 0.3;\n evidence.push('Syllabus present → concept signal');\n }\n\n // 2. Domain category heuristic\n if (PRODUCT_DOMAINS.includes(options.domainCategory)) {\n productScore += 0.2;\n evidence.push(`Domain ${options.domainCategory} → product倾向`);\n }\n if (CONCEPT_DOMAINS.includes(options.domainCategory)) {\n conceptScore += 0.2;\n evidence.push(`Domain ${options.domainCategory} → concept倾向`);\n }\n\n // 3. Verb pattern matching\n const hasBuildVerbs = BUILD_VERBS.some(v => text.includes(v));\n const hasUnderstandVerbs = UNDERSTAND_VERBS.some(v => text.includes(v));\n\n if (hasBuildVerbs) {\n productScore += 0.3;\n evidence.push('Build verbs detected in goal/description');\n }\n if (hasUnderstandVerbs) {\n conceptScore += 0.3;\n evidence.push('Understand verbs detected in goal/description');\n }\n\n // 4. Determine mode\n const total = productScore + conceptScore;\n if (total === 0) {\n return {\n learningMode: 'product',\n confidence: 0.3,\n evidence: [...evidence, 'No signals — defaulting to product'],\n };\n }\n\n // Check for hybrid\n if (productScore >= 0.3 && conceptScore >= 0.3) {\n const hybridConf = Math.min((productScore + conceptScore) / 2, 1.0);\n return {\n learningMode: 'hybrid',\n confidence: hybridConf,\n evidence: [...evidence, `Mixed signals: product=${productScore.toFixed(2)}, concept=${conceptScore.toFixed(2)} → hybrid`],\n };\n }\n\n if (productScore > conceptScore) {\n const raw = total > 0 ? productScore / total : 0.5;\n return {\n learningMode: 'product',\n confidence: Math.min(Math.max(raw, 0) + 0.2, 1.0),\n evidence,\n };\n }\n\n const raw = total > 0 ? conceptScore / total : 0.5;\n return {\n learningMode: 'concept',\n confidence: Math.min(Math.max(raw, 0) + 0.2, 1.0),\n evidence,\n };\n}\n","/**\n * Domain Profile Detection Orchestrator — combines all detection modules.\n */\n\nimport { detectInputType, type DetectInputTypeOptions } from './inputTypeDetector';\nimport { detectDomain, type DetectDomainOptions } from './domainDetector';\nimport { detectLearningMode } from './learningModeDetector';\nimport type { DomainProfile, GraphType } from '../schemas/domainProfileSchema';\nimport type { ParsedSyllabus } from '../parsers/syllabusParser';\n\nexport interface DetectDomainProfileOptions {\n repoUrl?: string;\n repoDir?: string;\n description?: string;\n goal?: string;\n syllabusText?: string;\n parsedSyllabus?: ParsedSyllabus;\n chapters?: string[];\n fileExtensions?: string[];\n techStack?: string;\n gradeBand?: [number, number];\n}\n\nexport function detectDomainProfile(options: DetectDomainProfileOptions): DomainProfile {\n const effectiveSyllabus = options.syllabusText || options.parsedSyllabus?.rawText || '';\n const inputResult = detectInputType({\n ...options,\n syllabusText: effectiveSyllabus,\n });\n\n const domainResult = detectDomain({\n description: options.description,\n goal: options.goal,\n syllabusText: effectiveSyllabus,\n techStack: options.techStack,\n fileExtensions: options.fileExtensions,\n repoUrl: options.repoUrl,\n });\n\n const modeResult = detectLearningMode({\n inputType: inputResult.inputType,\n domainCategory: domainResult.domainCategory,\n goal: options.goal,\n description: options.description,\n hasRepo: !!(options.repoUrl || options.repoDir),\n hasSyllabus: !!(effectiveSyllabus || (options.chapters && options.chapters.length > 0) || options.parsedSyllabus),\n });\n\n const graphType = determineGraphType(modeResult.learningMode);\n\n return {\n inputType: inputResult.inputType,\n domainCategory: (domainResult.domainCategory === 'other' && options.parsedSyllabus?.subject.domain)\n ? (options.parsedSyllabus.subject.domain as any)\n : domainResult.domainCategory,\n learningMode: modeResult.learningMode,\n graphType,\n confidence: {\n inputType: inputResult.confidence,\n domainCategory: domainResult.confidence,\n learningMode: modeResult.confidence,\n },\n evidence: [...inputResult.evidence, ...domainResult.evidence, ...modeResult.evidence],\n detectedTechStack: domainResult.detectedTechStack,\n detectedSubject: options.parsedSyllabus?.subject.title || domainResult.detectedSubject,\n detectedDomain: domainResult.domainCategory,\n goal: options.goal || '',\n description: options.description || '',\n repoUrl: options.repoUrl || '',\n repoDir: options.repoDir || '',\n syllabusText: effectiveSyllabus,\n };\n}\n\nfunction determineGraphType(learningMode: string): GraphType {\n switch (learningMode) {\n case 'product': return 'project_graph';\n case 'concept': return 'knowledge_graph';\n case 'hybrid': return 'hybrid_graph';\n default: return 'project_graph';\n }\n}\n"]}