@thanh01.pmt/domain-kit 0.1.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 (108) hide show
  1. package/README.md +1101 -0
  2. package/dist/assembly/index.cjs +213 -0
  3. package/dist/assembly/index.cjs.map +1 -0
  4. package/dist/assembly/index.d.cts +66 -0
  5. package/dist/assembly/index.d.ts +66 -0
  6. package/dist/assembly/index.mjs +4 -0
  7. package/dist/assembly/index.mjs.map +1 -0
  8. package/dist/chunk-3H2HX7PR.mjs +324 -0
  9. package/dist/chunk-3H2HX7PR.mjs.map +1 -0
  10. package/dist/chunk-3VVPSRAM.mjs +1297 -0
  11. package/dist/chunk-3VVPSRAM.mjs.map +1 -0
  12. package/dist/chunk-DRVOV5ZD.mjs +314 -0
  13. package/dist/chunk-DRVOV5ZD.mjs.map +1 -0
  14. package/dist/chunk-F4RZNBOE.mjs +3 -0
  15. package/dist/chunk-F4RZNBOE.mjs.map +1 -0
  16. package/dist/chunk-GEUDHZE7.mjs +446 -0
  17. package/dist/chunk-GEUDHZE7.mjs.map +1 -0
  18. package/dist/chunk-HH4UX65C.mjs +100 -0
  19. package/dist/chunk-HH4UX65C.mjs.map +1 -0
  20. package/dist/chunk-KMYENICQ.mjs +3 -0
  21. package/dist/chunk-KMYENICQ.mjs.map +1 -0
  22. package/dist/chunk-KNDBODUQ.mjs +153 -0
  23. package/dist/chunk-KNDBODUQ.mjs.map +1 -0
  24. package/dist/chunk-MM2RWYNW.mjs +3 -0
  25. package/dist/chunk-MM2RWYNW.mjs.map +1 -0
  26. package/dist/chunk-MOKNFLUD.mjs +851 -0
  27. package/dist/chunk-MOKNFLUD.mjs.map +1 -0
  28. package/dist/chunk-ONQHJ4OH.mjs +211 -0
  29. package/dist/chunk-ONQHJ4OH.mjs.map +1 -0
  30. package/dist/chunk-PM42MMDJ.mjs +516 -0
  31. package/dist/chunk-PM42MMDJ.mjs.map +1 -0
  32. package/dist/chunk-RKRNOVKO.mjs +166 -0
  33. package/dist/chunk-RKRNOVKO.mjs.map +1 -0
  34. package/dist/chunk-VFART56O.mjs +884 -0
  35. package/dist/chunk-VFART56O.mjs.map +1 -0
  36. package/dist/chunk-XMHKWHVK.mjs +218 -0
  37. package/dist/chunk-XMHKWHVK.mjs.map +1 -0
  38. package/dist/conceptEscalator-YfMKIKCZ.d.ts +40 -0
  39. package/dist/conceptEscalator-ltRLtPhf.d.cts +40 -0
  40. package/dist/concepts/index.cjs +155 -0
  41. package/dist/concepts/index.cjs.map +1 -0
  42. package/dist/concepts/index.d.cts +79 -0
  43. package/dist/concepts/index.d.ts +79 -0
  44. package/dist/concepts/index.mjs +4 -0
  45. package/dist/concepts/index.mjs.map +1 -0
  46. package/dist/curriculumFeedSchema-TEeQg2bY.d.cts +549 -0
  47. package/dist/curriculumFeedSchema-TEeQg2bY.d.ts +549 -0
  48. package/dist/detector/index.cjs +889 -0
  49. package/dist/detector/index.cjs.map +1 -0
  50. package/dist/detector/index.d.cts +112 -0
  51. package/dist/detector/index.d.ts +112 -0
  52. package/dist/detector/index.mjs +3 -0
  53. package/dist/detector/index.mjs.map +1 -0
  54. package/dist/domainProfileSchema-CwT3Ffsw.d.cts +105 -0
  55. package/dist/domainProfileSchema-CwT3Ffsw.d.ts +105 -0
  56. package/dist/extractors/index.cjs +387 -0
  57. package/dist/extractors/index.cjs.map +1 -0
  58. package/dist/extractors/index.d.cts +46 -0
  59. package/dist/extractors/index.d.ts +46 -0
  60. package/dist/extractors/index.mjs +4 -0
  61. package/dist/extractors/index.mjs.map +1 -0
  62. package/dist/feed/index.cjs +421 -0
  63. package/dist/feed/index.cjs.map +1 -0
  64. package/dist/feed/index.d.cts +23 -0
  65. package/dist/feed/index.d.ts +23 -0
  66. package/dist/feed/index.mjs +4 -0
  67. package/dist/feed/index.mjs.map +1 -0
  68. package/dist/graph/index.cjs +2167 -0
  69. package/dist/graph/index.cjs.map +1 -0
  70. package/dist/graph/index.d.cts +226 -0
  71. package/dist/graph/index.d.ts +226 -0
  72. package/dist/graph/index.mjs +4 -0
  73. package/dist/graph/index.mjs.map +1 -0
  74. package/dist/graphVerifier-DsTP9uAN.d.ts +37 -0
  75. package/dist/graphVerifier-QjgDAJce.d.cts +37 -0
  76. package/dist/hybridGraphSchema-BCgXicgA.d.cts +2840 -0
  77. package/dist/hybridGraphSchema-BCgXicgA.d.ts +2840 -0
  78. package/dist/index.cjs +5539 -0
  79. package/dist/index.cjs.map +1 -0
  80. package/dist/index.d.cts +18 -0
  81. package/dist/index.d.ts +18 -0
  82. package/dist/index.mjs +17 -0
  83. package/dist/index.mjs.map +1 -0
  84. package/dist/keywordExtractor-CKaXqSku.d.ts +34 -0
  85. package/dist/keywordExtractor-zPAz2isq.d.cts +34 -0
  86. package/dist/llmClient-ysPhLjcH.d.cts +16 -0
  87. package/dist/llmClient-ysPhLjcH.d.ts +16 -0
  88. package/dist/parsers/index.cjs +323 -0
  89. package/dist/parsers/index.cjs.map +1 -0
  90. package/dist/parsers/index.d.cts +98 -0
  91. package/dist/parsers/index.d.ts +98 -0
  92. package/dist/parsers/index.mjs +4 -0
  93. package/dist/parsers/index.mjs.map +1 -0
  94. package/dist/pipeline/index.cjs +2166 -0
  95. package/dist/pipeline/index.cjs.map +1 -0
  96. package/dist/pipeline/index.d.cts +45 -0
  97. package/dist/pipeline/index.d.ts +45 -0
  98. package/dist/pipeline/index.mjs +8 -0
  99. package/dist/pipeline/index.mjs.map +1 -0
  100. package/dist/projectGraphSchema-DnD7orZV.d.cts +2581 -0
  101. package/dist/projectGraphSchema-DnD7orZV.d.ts +2581 -0
  102. package/dist/schemas/index.cjs +675 -0
  103. package/dist/schemas/index.cjs.map +1 -0
  104. package/dist/schemas/index.d.cts +253 -0
  105. package/dist/schemas/index.d.ts +253 -0
  106. package/dist/schemas/index.mjs +4 -0
  107. package/dist/schemas/index.mjs.map +1 -0
  108. package/package.json +71 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemas/curriculumFeedSchema.ts"],"names":[],"mappings":";;;AAUO,IAAM,kBAAA,GAAqB,EAAE,MAAA,CAAO;AAAA,EACzC,GAAA,EAAK,EAAE,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EACnC,GAAA,EAAK,EAAE,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EACnC,YAAA,EAAc,EAAE,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,OAAA,CAAQ,EAAE;AAC9C,CAAC;AAEM,IAAM,2BAAA,GAA8B,EAAE,MAAA,CAAO;AAAA,EAClD,IAAA,EAAM,EAAE,MAAA,EAAO;AAAA,EACf,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,EAAE,CAAA;AAAA,EAC7B,aAAA,EAAe,EAAE,MAAA,EAAO,CAAE,KAAI,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACvD,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,CAAC,cAAA,EAAgB,mBAAmB,mBAAmB,CAAC,CAAA,CAAE,OAAA,CAAQ,cAAc;AAClG,CAAC;AAEM,IAAM,cAAA,GAAiB,EAAE,MAAA,CAAO;AAAA,EACrC,EAAA,EAAI,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,OAAA,EAAS,SAAA,EAAW,cAAc,CAAC,CAAA;AAAA,EACjD,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACtB,aAAA,EAAe,EAAE,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EAC7C,QAAA,EAAU,kBAAA;AAAA,EACV,mBAAmB,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,WAAA,EAAY;AAAA,EAChD,UAAA,EAAY,CAAA,CAAE,IAAA,CAAK,CAAC,YAAY,YAAA,EAAc,OAAA,EAAS,SAAA,EAAW,UAAA,EAAY,QAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,QAAQ,IAAI,CAAA;AAAA,EAChH,UAAA,EAAY,CAAA,CAAE,IAAA,CAAK,CAAC,KAAA,EAAO,KAAA,EAAO,KAAK,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,IAAI,CAAA;AAAA,EACjE,gBAAA,EAAkB,CAAA,CAAE,IAAA,CAAK,CAAC,KAAA,EAAO,YAAY,SAAS,CAAC,CAAA,CAAE,OAAA,CAAQ,UAAU,CAAA;AAAA,EAC3E,WAAA,EAAa,EAAE,MAAA,CAAO;AAAA,IACpB,qBAAqB,CAAA,CAAE,KAAA,CAAM,2BAA2B,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,IACpE,kBAAA,EAAoB,EAAE,MAAA,EAAO,CAAE,KAAI,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,CAAC;AAAA,GAC7D,EAAE,OAAA,CAAQ,EAAE,qBAAqB,EAAC,EAAG,kBAAA,EAAoB,CAAA,EAAG,CAAA;AAAA,EAC7D,UAAA,EAAY,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,MAAA,CAAO,EAAE,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,GAAG,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,OAAA,CAAQ,EAAE,CAAA,EAAG,CAAC,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EACvG,YAAY,CAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,QAAQ,IAAI,CAAA;AAAA,EAC9C,aAAa,CAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA;AAAA;AAAA,EAI/C,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,EAAE,CAAA;AAAA,EAC/B,gBAAA,EAAkB,CAAA,CAAE,IAAA,CAAK,CAAC,KAAA,EAAO,UAAU,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,IAAI;AACvE,CAAC;AAEM,IAAM,cAAA,GAAiB,EAAE,MAAA,CAAO;AAAA,EACrC,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACtB,EAAA,EAAI,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,WAAA,EAAa,MAAM,CAAC,CAAA;AAAA,EAClC,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,EAAE;AAC/B,CAAC;AAEM,IAAM,kBAAA,GAAqB,EAAE,MAAA,CAAO;AAAA,EACzC,EAAA,EAAI,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACtB,QAAA,EAAU,EAAE,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,EACnC,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,EAAE;AAClC,CAAC;AAEM,IAAM,eAAA,GAAkB,EAAE,MAAA,CAAO;AAAA,EACtC,EAAA,EAAI,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpB,OAAO,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,QAAA,EAAS;AAAA,EACjC,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACtB,kBAAA,EAAoB,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACpC,QAAA,EAAU,EAAE,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,IAAI,CAAC;AACrC,CAAC;AAGM,IAAM,oBAAA,GAAuB,EAAE,MAAA,CAAO;AAAA,EAC3C,cAAA,EAAgB,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EAC3B,MAAA,EAAQ,EAAE,MAAA,CAAO;AAAA,IACf,YAAY,CAAA,CAAE,IAAA,CAAK,CAAC,eAAA,EAAiB,iBAAA,EAAmB,cAAc,CAAC,CAAA;AAAA,IACvE,QAAA,EAAU,EAAE,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,IACxC,mBAAA,EAAqB,EAAE,MAAA,EAAO,CAAE,KAAI,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,CAAC;AAAA,GAC9D,CAAA;AAAA,EACD,gBAAgB,CAAA,CAAE,KAAA,CAAM,cAAc,CAAA,CAAE,GAAA,CAAI,GAAG,yDAAyD,CAAA;AAAA,EACxG,kBAAkB,CAAA,CAAE,KAAA,CAAM,cAAc,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EACpD,qBAAqB,CAAA,CAAE,KAAA,CAAM,kBAAkB,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA;AAAA;AAAA,EAG3D,QAAQ,CAAA,CAAE,KAAA,CAAM,eAAe,CAAA,CAAE,OAAA,CAAQ,EAAE;AAC7C,CAAC;AAQM,SAAS,uBAAuB,IAAA,EAA+B;AACpE,EAAA,MAAM,MAAA,GAAS,oBAAA,CAAqB,KAAA,CAAM,IAAI,CAAA;AAC9C,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,MAAA,CAAO,cAAA,CAAe,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAC1D,EAAA,IAAI,GAAA,CAAI,IAAA,KAAS,MAAA,CAAO,cAAA,CAAe,MAAA,EAAQ;AAC7C,IAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,EAC/D;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,OAAO,gBAAA,EAAkB;AACvC,IAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA,IAAK,CAAC,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,EAAG;AACtC,MAAA,MAAM,IAAI,MAAM,uBAAA,GAA0B,CAAA,CAAE,OAAO,MAAA,GAAS,CAAA,CAAE,KAAK,0BAA0B,CAAA;AAAA,IAC/F;AACA,IAAA,IAAI,CAAA,CAAE,SAAS,CAAA,CAAE,EAAA,QAAU,IAAI,KAAA,CAAM,oCAAA,GAAuC,CAAA,CAAE,IAAI,CAAA;AAAA,EACpF;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,OAAO,mBAAA,EAAqB;AAC1C,IAAA,KAAA,MAAW,EAAA,IAAM,EAAE,QAAA,EAAU;AAC3B,MAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,WAAA,GAAc,CAAA,CAAE,EAAA,GAAK,2BAAA,GAA8B,EAAE,CAAA;AAAA,IACzF;AAAA,EACF;AACA,EAAA,KAAA,MAAW,EAAA,IAAM,OAAO,MAAA,EAAQ;AAC9B,IAAA,KAAA,MAAW,EAAA,IAAM,GAAG,QAAA,EAAU;AAC5B,MAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,QAAA,GAAW,EAAA,CAAG,EAAA,GAAK,2BAAA,GAA8B,EAAE,CAAA;AAAA,IACvF;AAAA,EACF;AACA,EAAA,MAAM,WAAW,MAAA,CAAO,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AAC9C,EAAA,IAAI,IAAI,GAAA,CAAI,QAAQ,CAAA,CAAE,IAAA,KAAS,SAAS,MAAA,EAAQ,MAAM,IAAI,KAAA,CAAM,8CAA8C,CAAA;AAC9G,EAAA,OAAO,MAAA;AACT","file":"chunk-HH4UX65C.mjs","sourcesContent":["import { z } from 'zod';\n\n/**\n * CurriculumFeed v2 — normalized, planner-ready projection of a domain graph.\n * Consumers: curriculum-kit Curriculum Planner (see docs/ideas/2026-08-30-curriculum-feed-v2-output.md).\n * Guarantees enforced here: cycle-free is the CALLER's verifier job; the feed\n * itself guarantees resolution (edges/keywords reference emitted nodes) and\n * non-emptiness.\n */\n\nexport const FeedKeywordsSchema = z.object({\n all: z.array(z.string()).default([]),\n new: z.array(z.string()).default([]),\n prerequisite: z.array(z.string()).default([]),\n});\n\nexport const FeedScaffoldCandidateSchema = z.object({\n item: z.string(),\n reason: z.string().default(''),\n minutes_saved: z.number().int().nonnegative().default(0),\n suggest: z.enum(['provide_full', 'provide_partial', 'provide_reference']).default('provide_full'),\n});\n\nexport const FeedNodeSchema = z.object({\n id: z.string().min(1),\n kind: z.enum(['skill', 'concept', 'product_step']),\n name: z.string().min(1),\n concept_codes: z.array(z.string()).default([]),\n keywords: FeedKeywordsSchema,\n estimated_minutes: z.number().int().nonnegative(),\n bloom_hint: z.enum(['Remember', 'Understand', 'Apply', 'Analyze', 'Evaluate', 'Create']).nullable().default(null),\n depth_hint: z.enum(['ulo', 'cio', 'sio']).nullable().default(null),\n completion_level: z.enum(['mvp', 'standard', 'stretch']).default('standard'),\n scaffolding: z.object({\n scaffold_candidates: z.array(FeedScaffoldCandidateSchema).default([]),\n core_value_minutes: z.number().int().nonnegative().default(0),\n }).default({ scaffold_candidates: [], core_value_minutes: 0 }),\n references: z.array(z.object({ file: z.string().min(1), evidence: z.string().default('') })).default([]),\n feature_id: z.string().nullable().default(null),\n concept_ref: z.string().nullable().default(null),\n // Progressive-completion bookkeeping (feed v2, additive):\n // phase_id = development phase that introduces/uses this node;\n // introduce_aspect = how the phase teaches a concept node (first intro vs advanced revisit).\n phase_id: z.string().default(''),\n introduce_aspect: z.enum(['new', 'advanced']).nullable().default(null),\n});\n\nexport const FeedEdgeSchema = z.object({\n from: z.string().min(1),\n to: z.string().min(1),\n kind: z.enum(['knowledge', 'task']),\n reason: z.string().default(''),\n});\n\nexport const FeedGroupingSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n node_ids: z.array(z.string()).min(1),\n rationale: z.string().default(''),\n});\n\nexport const FeedPhaseSchema = z.object({\n id: z.string().min(1),\n order: z.number().int().positive(),\n name: z.string().min(1),\n product_completion: z.string().min(1),\n node_ids: z.array(z.string()).min(1),\n});\nexport type FeedPhase = z.infer<typeof FeedPhaseSchema>;\n\nexport const CurriculumFeedSchema = z.object({\n schema_version: z.literal(2),\n source: z.object({\n graph_type: z.enum(['project_graph', 'knowledge_graph', 'hybrid_graph']),\n warnings: z.array(z.string()).default([]),\n hallucination_count: z.number().int().nonnegative().default(0),\n }),\n learning_nodes: z.array(FeedNodeSchema).min(1, 'curriculum feed must contain at least one learning node'),\n dependency_edges: z.array(FeedEdgeSchema).default([]),\n suggested_groupings: z.array(FeedGroupingSchema).default([]),\n // Progressive completion phases (cross-feature). When non-empty, these — not\n // suggested_groupings — define the teaching sequence and unit structure.\n phases: z.array(FeedPhaseSchema).default([]),\n});\n\nexport type CurriculumFeed = z.infer<typeof CurriculumFeedSchema>;\nexport type FeedNode = z.infer<typeof FeedNodeSchema>;\nexport type FeedEdge = z.infer<typeof FeedEdgeSchema>;\nexport type FeedGrouping = z.infer<typeof FeedGroupingSchema>;\n\n/** Strict pre-save resolution validation — fail-closed, no defaulted-empty graphs. */\nexport function validateCurriculumFeed(feed: unknown): CurriculumFeed {\n const parsed = CurriculumFeedSchema.parse(feed);\n const ids = new Set(parsed.learning_nodes.map((n) => n.id));\n if (ids.size !== parsed.learning_nodes.length) {\n throw new Error('curriculum feed contains duplicate node ids');\n }\n for (const e of parsed.dependency_edges) {\n if (!ids.has(e.from) || !ids.has(e.to)) {\n throw new Error('curriculum feed edge ' + e.from + ' -> ' + e.to + ' references unknown node');\n }\n if (e.from === e.to) throw new Error('curriculum feed self-loop edge on ' + e.from);\n }\n for (const g of parsed.suggested_groupings) {\n for (const id of g.node_ids) {\n if (!ids.has(id)) throw new Error('grouping ' + g.id + ' references unknown node ' + id);\n }\n }\n for (const ph of parsed.phases) {\n for (const id of ph.node_ids) {\n if (!ids.has(id)) throw new Error('phase ' + ph.id + ' references unknown node ' + id);\n }\n }\n const phaseIds = parsed.phases.map((p) => p.id);\n if (new Set(phaseIds).size !== phaseIds.length) throw new Error('curriculum feed contains duplicate phase ids');\n return parsed;\n}\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-KMYENICQ.mjs.map
3
+ //# sourceMappingURL=chunk-KMYENICQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-KMYENICQ.mjs"}
@@ -0,0 +1,153 @@
1
+ // src/concepts/conceptResolver.ts
2
+ var SOURCE_THRESHOLDS = {
3
+ docstring: 0.45,
4
+ readme_description: 0.45,
5
+ readme: 0.5,
6
+ type_declaration: 0.55,
7
+ function_signature: 0.55,
8
+ import: 0.6,
9
+ property_wrapper: 0.55,
10
+ error_handling: 0.6,
11
+ config: 0.6,
12
+ framework_usage: 0.45
13
+ };
14
+ var DEFAULT_THRESHOLD = 0.55;
15
+ function uloCioAwareScore(query, depth, conceptData) {
16
+ const queryTerms = new Set(query.toLowerCase().split(/\s+/));
17
+ let targetText = "";
18
+ if (depth === "sio") {
19
+ targetText = conceptData.keywords || "";
20
+ } else if (depth === "cio") {
21
+ targetText = [conceptData.description || "", conceptData.cio || ""].join(" ");
22
+ } else {
23
+ targetText = [conceptData.ulo || "", conceptData.description || ""].join(" ");
24
+ }
25
+ const targetTerms = new Set(targetText.toLowerCase().split(/\s+/));
26
+ if (!queryTerms.size || !targetTerms.size) return 0;
27
+ let overlap = 0;
28
+ for (const t of queryTerms) {
29
+ if (targetTerms.has(t)) overlap++;
30
+ }
31
+ return Math.min(overlap / queryTerms.size, 1);
32
+ }
33
+ function inferFieldsFromGoal(goal) {
34
+ const goalLower = goal.toLowerCase();
35
+ const fieldKeywords = {
36
+ ASE: ["algorithm", "software", "programming", "code", "develop", "build", "app"],
37
+ DAI: ["data", "database", "storage", "query", "sql", "analytics"],
38
+ CSN: ["network", "protocol", "server", "client", "api", "http"],
39
+ HCI: ["user", "interface", "ui", "ux", "interaction", "design"],
40
+ MOB: ["mobile", "ios", "android", "swift", "kotlin", "flutter"],
41
+ WEB: ["web", "html", "css", "javascript", "react", "vue"]
42
+ };
43
+ const matched = [];
44
+ for (const [code, keywords] of Object.entries(fieldKeywords)) {
45
+ if (keywords.some((kw) => goalLower.includes(kw))) matched.push(code);
46
+ }
47
+ return matched.length > 0 ? matched : ["ASE"];
48
+ }
49
+ function inferDepthFromSource(source) {
50
+ const uloSources = ["docstring", "readme", "readme_description", "framework_usage"];
51
+ const cioSources = ["type_declaration", "function_signature", "config"];
52
+ if (uloSources.includes(source)) return "ulo";
53
+ if (cioSources.includes(source)) return "cio";
54
+ return "sio";
55
+ }
56
+ async function resolveConcepts(options) {
57
+ const { keywords, goal, embeddings, depthOverrides, topK = 3, threshold = DEFAULT_THRESHOLD, llmConfig } = options;
58
+ inferFieldsFromGoal(goal);
59
+ const resolved = [];
60
+ const proposed = [];
61
+ const hasEmbeddings = Object.keys(embeddings || {}).length > 0 && Object.values(embeddings || {}).some((d) => d.embedding && d.embedding.length > 0);
62
+ let search_mode = hasEmbeddings ? "embedding" : "keyword_overlap";
63
+ const concepts = embeddings || {};
64
+ for (const kwData of keywords) {
65
+ const keyword = kwData.keyword;
66
+ const source = kwData.source;
67
+ const depth = depthOverrides?.get(keyword) || inferDepthFromSource(source);
68
+ const scored = [];
69
+ for (const [code, data] of Object.entries(concepts)) {
70
+ const conceptKeywords = data.keywords || "";
71
+ const conceptDesc = data.description || "";
72
+ const conceptUlo = data.ulo;
73
+ const conceptCio = data.cio;
74
+ const awareScore = uloCioAwareScore(keyword, depth, {
75
+ keywords: conceptKeywords,
76
+ description: conceptDesc,
77
+ ulo: conceptUlo,
78
+ cio: conceptCio
79
+ });
80
+ const queryTerms = new Set(keyword.toLowerCase().split(/\s+/));
81
+ const allTerms = new Set([
82
+ ...conceptKeywords.toLowerCase().split(/\s+/),
83
+ ...conceptDesc.toLowerCase().split(/\s+/),
84
+ ...(conceptUlo || "").toLowerCase().split(/\s+/),
85
+ ...(conceptCio || "").toLowerCase().split(/\s+/)
86
+ ].filter(Boolean));
87
+ let overlapCount = 0;
88
+ for (const t of queryTerms) {
89
+ if (allTerms.has(t)) overlapCount++;
90
+ }
91
+ const fallbackScore = queryTerms.size > 0 ? Math.min(overlapCount / queryTerms.size, 1) : 0;
92
+ const usedAware = awareScore >= fallbackScore;
93
+ const finalScore = usedAware ? awareScore : fallbackScore;
94
+ if (finalScore > 0) {
95
+ scored.push({
96
+ code,
97
+ name: data.name || code,
98
+ description: conceptDesc,
99
+ keywords: conceptKeywords,
100
+ ulo: conceptUlo,
101
+ cio: conceptCio,
102
+ score: finalScore,
103
+ matched_level: usedAware ? depth : "sio",
104
+ method: hasEmbeddings && data.embedding && data.embedding.length > 0 ? "embedding" : "keyword_overlap"
105
+ });
106
+ }
107
+ }
108
+ scored.sort((a, b) => b.score - a.score);
109
+ const topMatches = scored.slice(0, topK);
110
+ if (topMatches.length === 0) {
111
+ proposed.push({
112
+ keyword,
113
+ source,
114
+ depth,
115
+ reason: "No matches in Master Tree"
116
+ });
117
+ continue;
118
+ }
119
+ const effThreshold = SOURCE_THRESHOLDS[source] || threshold;
120
+ const topMatch = topMatches[0];
121
+ if (topMatch.score >= effThreshold) {
122
+ resolved.push({
123
+ keyword,
124
+ source,
125
+ depth,
126
+ concept_codes: topMatches.filter((m) => m.score >= effThreshold).map((m) => m.code),
127
+ matches: topMatches
128
+ });
129
+ } else {
130
+ proposed.push({
131
+ keyword,
132
+ source,
133
+ depth,
134
+ best_match: topMatch,
135
+ reason: `Low confidence (${topMatch.score.toFixed(2)} < ${effThreshold})`
136
+ });
137
+ }
138
+ }
139
+ return {
140
+ resolved,
141
+ proposed,
142
+ summary: {
143
+ total_keywords: keywords.length,
144
+ resolved_count: resolved.length,
145
+ proposed_count: proposed.length,
146
+ search_mode
147
+ }
148
+ };
149
+ }
150
+
151
+ export { resolveConcepts };
152
+ //# sourceMappingURL=chunk-KNDBODUQ.mjs.map
153
+ //# sourceMappingURL=chunk-KNDBODUQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/concepts/conceptResolver.ts"],"names":[],"mappings":"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","file":"chunk-KNDBODUQ.mjs","sourcesContent":["/**\n * Concept resolution — maps keywords to Master Tree concepts.\n *\n * Ported from knowledge-tree/resolve_concepts.py\n * Uses ULO/CIO/SIO-aware matching:\n * - SIO keywords → match against concept.keywords (tech-specific)\n * - CIO keywords → match against concept.description (mechanism)\n * - ULO keywords → match against concept.ulo (what/why, tech-independent)\n *\n * Fallback: keyword overlap matching when embeddings unavailable.\n *\n * NOTE: This module requires sentence-transformers Python package for embeddings.\n * In pure TypeScript mode, it falls back to keyword overlap matching.\n */\n\nimport { createLlmClient, llmChatJson, type LlmClientConfig } from '../utils/llmClient';\nimport type { Keyword } from '../extractors/keywordExtractor';\n\nexport interface ResolvedConcept {\n keyword: string;\n source: string;\n depth: 'ulo' | 'cio' | 'sio';\n concept_codes: string[];\n matches: ConceptMatch[];\n override?: boolean;\n rechecked?: boolean;\n}\n\nexport interface ConceptMatch {\n code: string;\n name: string;\n description: string;\n keywords: string;\n ulo?: string;\n cio?: string;\n score: number;\n matched_level: 'ulo' | 'cio' | 'sio';\n method: 'embedding' | 'keyword_overlap';\n}\n\nexport interface ProposedConcept {\n keyword: string;\n source: string;\n depth: 'ulo' | 'cio' | 'sio';\n reason: string;\n best_match?: ConceptMatch;\n}\n\nexport interface ResolveConceptsResult {\n resolved: ResolvedConcept[];\n proposed: ProposedConcept[];\n summary: {\n total_keywords: number;\n resolved_count: number;\n proposed_count: number;\n search_mode: string;\n };\n}\n\nexport interface ResolveConceptsOptions {\n keywords: Keyword[];\n goal: string;\n embeddings?: Record<string, { embedding?: number[]; name?: string; description?: string; keywords?: string; ulo?: string; cio?: string }>;\n /** Pre-computed depth from conceptEscalator — overrides inferDepthFromSource */\n depthOverrides?: Map<string, 'ulo' | 'cio' | 'sio'>;\n topK?: number;\n threshold?: number;\n llmConfig?: LlmClientConfig;\n}\n\n// Source-based thresholds\nconst SOURCE_THRESHOLDS: Record<string, number> = {\n docstring: 0.45,\n readme_description: 0.45,\n readme: 0.50,\n type_declaration: 0.55,\n function_signature: 0.55,\n import: 0.60,\n property_wrapper: 0.55,\n error_handling: 0.60,\n config: 0.60,\n framework_usage: 0.45,\n};\n\nconst DEFAULT_THRESHOLD = 0.55;\n\nfunction cosineSimilarity(a: number[], b: number[]): number {\n if (!a.length || !b.length || a.length !== b.length) return 0;\n let dot = 0, normA = 0, normB = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n if (normA === 0 || normB === 0) return 0;\n return dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n\n/**\n * ULO/CIO/SIO-aware keyword overlap scoring.\n * Matches against different concept fields based on depth level.\n */\nfunction uloCioAwareScore(\n query: string,\n depth: 'ulo' | 'cio' | 'sio',\n conceptData: { keywords?: string; description?: string; ulo?: string; cio?: string },\n): number {\n const queryTerms = new Set(query.toLowerCase().split(/\\s+/));\n\n // Choose which fields to match based on depth\n let targetText = '';\n if (depth === 'sio') {\n // SIO: match against keywords (tech-specific terms)\n targetText = conceptData.keywords || '';\n } else if (depth === 'cio') {\n // CIO: match against description + cio (mechanism)\n targetText = [conceptData.description || '', conceptData.cio || ''].join(' ');\n } else {\n // ULO: match against ulo + description (what/why, tech-independent)\n targetText = [conceptData.ulo || '', conceptData.description || ''].join(' ');\n }\n\n const targetTerms = new Set(targetText.toLowerCase().split(/\\s+/));\n if (!queryTerms.size || !targetTerms.size) return 0;\n\n let overlap = 0;\n for (const t of queryTerms) {\n if (targetTerms.has(t)) overlap++;\n }\n return Math.min(overlap / queryTerms.size, 1.0);\n}\n\n\nfunction inferFieldsFromGoal(goal: string): string[] {\n const goalLower = goal.toLowerCase();\n const fieldKeywords: Record<string, string[]> = {\n ASE: ['algorithm', 'software', 'programming', 'code', 'develop', 'build', 'app'],\n DAI: ['data', 'database', 'storage', 'query', 'sql', 'analytics'],\n CSN: ['network', 'protocol', 'server', 'client', 'api', 'http'],\n HCI: ['user', 'interface', 'ui', 'ux', 'interaction', 'design'],\n MOB: ['mobile', 'ios', 'android', 'swift', 'kotlin', 'flutter'],\n WEB: ['web', 'html', 'css', 'javascript', 'react', 'vue'],\n };\n\n const matched: string[] = [];\n for (const [code, keywords] of Object.entries(fieldKeywords)) {\n if (keywords.some(kw => goalLower.includes(kw))) matched.push(code);\n }\n return matched.length > 0 ? matched : ['ASE'];\n}\n\n/**\n * Infer depth from keyword source and context.\n */\nfunction inferDepthFromSource(source: string): 'ulo' | 'cio' | 'sio' {\n const uloSources = ['docstring', 'readme', 'readme_description', 'framework_usage'];\n const cioSources = ['type_declaration', 'function_signature', 'config'];\n\n if (uloSources.includes(source)) return 'ulo';\n if (cioSources.includes(source)) return 'cio';\n return 'sio';\n}\n\n/**\n * Resolve keywords to concepts using ULO/CIO/SIO-aware matching.\n */\nexport async function resolveConcepts(\n options: ResolveConceptsOptions,\n): Promise<ResolveConceptsResult> {\n const { keywords, goal, embeddings, depthOverrides, topK = 3, threshold = DEFAULT_THRESHOLD, llmConfig } = options;\n\n const relevantFields = inferFieldsFromGoal(goal);\n const resolved: ResolvedConcept[] = [];\n const proposed: ProposedConcept[] = [];\n const hasEmbeddings = Object.keys(embeddings || {}).length > 0 &&\n Object.values(embeddings || {}).some(d => d.embedding && d.embedding.length > 0);\n let search_mode = hasEmbeddings ? 'embedding' : 'keyword_overlap';\n\n const concepts = embeddings || {};\n\n for (const kwData of keywords) {\n const keyword = kwData.keyword;\n const source = kwData.source;\n // Use escalator's depth override if available, else infer from source\n const depth = depthOverrides?.get(keyword) || inferDepthFromSource(source);\n\n // Search concepts via ULO/CIO/SIO-aware matching\n const scored: ConceptMatch[] = [];\n for (const [code, data] of Object.entries(concepts)) {\n const conceptKeywords = data.keywords || '';\n const conceptDesc = data.description || '';\n const conceptUlo = (data as Record<string, unknown>).ulo as string | undefined;\n const conceptCio = (data as Record<string, unknown>).cio as string | undefined;\n\n // Primary: ULO/CIO-aware score based on depth level\n const awareScore = uloCioAwareScore(keyword, depth, {\n keywords: conceptKeywords,\n description: conceptDesc,\n ulo: conceptUlo,\n cio: conceptCio,\n });\n\n // Fallback: broad keyword overlap across all fields\n const queryTerms = new Set(keyword.toLowerCase().split(/\\s+/));\n const allTerms = new Set([\n ...conceptKeywords.toLowerCase().split(/\\s+/),\n ...conceptDesc.toLowerCase().split(/\\s+/),\n ...(conceptUlo || '').toLowerCase().split(/\\s+/),\n ...(conceptCio || '').toLowerCase().split(/\\s+/),\n ].filter(Boolean));\n let overlapCount = 0;\n for (const t of queryTerms) { if (allTerms.has(t)) overlapCount++; }\n const fallbackScore = queryTerms.size > 0 ? Math.min(overlapCount / queryTerms.size, 1.0) : 0;\n\n // Use the higher score, but track which method won\n const usedAware = awareScore >= fallbackScore;\n const finalScore = usedAware ? awareScore : fallbackScore;\n\n if (finalScore > 0) {\n scored.push({\n code,\n name: data.name || code,\n description: conceptDesc,\n keywords: conceptKeywords,\n ulo: conceptUlo,\n cio: conceptCio,\n score: finalScore,\n matched_level: usedAware ? depth : 'sio',\n method: hasEmbeddings && data.embedding && data.embedding.length > 0 ? 'embedding' : 'keyword_overlap',\n });\n }\n }\n\n scored.sort((a, b) => b.score - a.score);\n const topMatches = scored.slice(0, topK);\n\n if (topMatches.length === 0) {\n proposed.push({\n keyword,\n source,\n depth,\n reason: 'No matches in Master Tree',\n });\n continue;\n }\n\n const effThreshold = SOURCE_THRESHOLDS[source] || threshold;\n const topMatch = topMatches[0];\n\n if (topMatch.score >= effThreshold) {\n resolved.push({\n keyword,\n source,\n depth,\n concept_codes: topMatches.filter(m => m.score >= effThreshold).map(m => m.code),\n matches: topMatches,\n });\n } else {\n proposed.push({\n keyword,\n source,\n depth,\n best_match: topMatch,\n reason: `Low confidence (${topMatch.score.toFixed(2)} < ${effThreshold})`,\n });\n }\n }\n\n return {\n resolved,\n proposed,\n summary: {\n total_keywords: keywords.length,\n resolved_count: resolved.length,\n proposed_count: proposed.length,\n search_mode,\n },\n };\n}\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-MM2RWYNW.mjs.map
3
+ //# sourceMappingURL=chunk-MM2RWYNW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-MM2RWYNW.mjs"}