@thanh01.pmt/domain-kit 0.3.0 → 0.5.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -11
  3. package/dist/{chunk-MSRKUZLY.mjs → chunk-E4GCCWJO.mjs} +32 -2
  4. package/dist/chunk-E4GCCWJO.mjs.map +1 -0
  5. package/dist/{chunk-MCHHEBH3.mjs → chunk-G7HLFMD2.mjs} +5 -5
  6. package/dist/{chunk-MCHHEBH3.mjs.map → chunk-G7HLFMD2.mjs.map} +1 -1
  7. package/dist/{chunk-LKSVTRQE.mjs → chunk-TWKIVUTQ.mjs} +33 -3
  8. package/dist/chunk-TWKIVUTQ.mjs.map +1 -0
  9. package/dist/{chunk-Y7MRFFDJ.mjs → chunk-TYXSJUQU.mjs} +100 -9
  10. package/dist/chunk-TYXSJUQU.mjs.map +1 -0
  11. package/dist/curriculumFeedEmitter-T7NUBLAM.mjs +4 -0
  12. package/dist/{curriculumFeedEmitter-FYAWMPE6.mjs.map → curriculumFeedEmitter-T7NUBLAM.mjs.map} +1 -1
  13. package/dist/{curriculumFeedSchema-C8ZP3XMi.d.ts → curriculumFeedSchema-DUFwFyr2.d.cts} +196 -0
  14. package/dist/{curriculumFeedSchema-C8ZP3XMi.d.cts → curriculumFeedSchema-DUFwFyr2.d.ts} +196 -0
  15. package/dist/feed/index.cjs +60 -0
  16. package/dist/feed/index.cjs.map +1 -1
  17. package/dist/feed/index.d.cts +1 -1
  18. package/dist/feed/index.d.ts +1 -1
  19. package/dist/feed/index.mjs +2 -2
  20. package/dist/graph/index.cjs +98 -6
  21. package/dist/graph/index.cjs.map +1 -1
  22. package/dist/graph/index.d.cts +1 -1
  23. package/dist/graph/index.d.ts +1 -1
  24. package/dist/graph/index.mjs +1 -1
  25. package/dist/{hybridGraphPipeline-NZAWAPt_.d.ts → hybridGraphPipeline-DXQDbBEj.d.ts} +14 -2
  26. package/dist/{hybridGraphPipeline-BhFyh3cm.d.cts → hybridGraphPipeline-dT-bio-3.d.cts} +14 -2
  27. package/dist/index.cjs +158 -6
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +2 -2
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.mjs +4 -4
  32. package/dist/pipeline/index.cjs +157 -6
  33. package/dist/pipeline/index.cjs.map +1 -1
  34. package/dist/pipeline/index.d.cts +2 -2
  35. package/dist/pipeline/index.d.ts +2 -2
  36. package/dist/pipeline/index.mjs +4 -4
  37. package/dist/schemas/index.cjs +30 -0
  38. package/dist/schemas/index.cjs.map +1 -1
  39. package/dist/schemas/index.d.cts +1 -1
  40. package/dist/schemas/index.d.ts +1 -1
  41. package/dist/schemas/index.mjs +1 -1
  42. package/package.json +9 -10
  43. package/dist/chunk-LKSVTRQE.mjs.map +0 -1
  44. package/dist/chunk-MSRKUZLY.mjs.map +0 -1
  45. package/dist/chunk-Y7MRFFDJ.mjs.map +0 -1
  46. package/dist/curriculumFeedEmitter-FYAWMPE6.mjs +0 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Tony Pham
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -151,7 +151,8 @@ const feed = emitCurriculumFeed(result.projectGraph); // or knowledgeGraph or h
151
151
  console.log(feed.learning_nodes.length); // unified nodes ready for planner
152
152
  console.log(feed.dependency_edges.length); // knowledge + task edges
153
153
  console.log(feed.suggested_groupings); // feature/category groupings
154
- // Each node has: bloom_hint, depth_hint, keywords.new/.prerequisite
154
+ console.log(feed.phases.length); // non-empty ⇒ learning_nodes are in teaching order (phases define units)
155
+ // Each node has: bloom_hint, depth_hint, keywords.new/.prerequisite, introduce_aspect, user_visible_deliverable
155
156
  ```
156
157
 
157
158
  ---
@@ -399,10 +400,11 @@ All schemas are Zod-validated TypeScript types.
399
400
  | `DomainProfileSchema` | `domainProfileSchema.ts` | Domain detection output |
400
401
  | `HardwareFeatureExtension` | `domainExtensions.ts` | Hardware overlay (wiring, materials) |
401
402
  | `ThreeDesignFeatureExtension` | `domainExtensions.ts` | 3D Design overlay (shapes, dimensions) |
402
- | `CurriculumFeedSchema` | `curriculumFeedSchema.ts` | Planner-ready normalized feed (nodes, edges, groupings) |
403
+ | `CurriculumFeedSchema` | `curriculumFeedSchema.ts` | Planner-ready normalized feed (nodes, edges, groupings, phases) |
403
404
  | `FeedNodeSchema` | `curriculumFeedSchema.ts` | Individual learning node (concept, skill, or product step) |
404
405
  | `FeedEdgeSchema` | `curriculumFeedSchema.ts` | Dependency edge (knowledge or task) |
405
406
  | `FeedGroupingSchema` | `curriculumFeedSchema.ts` | Suggested grouping of nodes (feature or category) |
407
+ | `FeedPhaseSchema` | `curriculumFeedSchema.ts` | Development phase — when non-empty, defines teaching sequence and unit structure |
406
408
 
407
409
  ### Key Types
408
410
 
@@ -486,9 +488,10 @@ type AssembledRoadmap = {
486
488
  type CurriculumFeed = {
487
489
  schema_version: 2;
488
490
  source: { graph_type: 'project_graph' | 'knowledge_graph' | 'hybrid_graph'; warnings: string[]; hallucination_count: number };
489
- learning_nodes: FeedNode[];
491
+ learning_nodes: FeedNode[]; // in TEACHING ORDER when phases[] is non-empty
490
492
  dependency_edges: FeedEdge[];
491
493
  suggested_groupings: FeedGrouping[];
494
+ phases: FeedPhase[]; // when non-empty, THESE — not suggested_groupings — define the teaching sequence and unit structure
492
495
  }
493
496
 
494
497
  type FeedNode = {
@@ -505,6 +508,20 @@ type FeedNode = {
505
508
  references: { file: string; evidence: string }[];
506
509
  feature_id: string | null;
507
510
  concept_ref: string | null;
511
+ phase_id: string; // development phase that introduces/uses this node ('' on legacy feeds)
512
+ introduce_aspect: 'new' | 'advanced' | 'preview' | null; // first intro / advanced revisit / preview priming
513
+ user_visible_deliverable: string; // step's outcome.user_visible — checkpoint candidate for session cutting ('' on concept nodes)
514
+ depth_variants?: { ulo: number; cio: number; sio: number }; // minutes per depth level — reconciler price list (ULO ≤ CIO ≤ SIO)
515
+ depth_scaffold_candidates?: { from_depth: 'ulo' | 'cio' | 'sio'; to_depth: 'ulo' | 'cio' | 'sio'; minutes_saved: number; reason: string }[]; // DEPTH downgrades (SIO→CIO, CIO→ULO) — parallel to scaffold_candidates
516
+ is_core: boolean; // Master-Tree core concept — never depth-downgraded; escalate instead
517
+ }
518
+
519
+ type FeedPhase = {
520
+ id: string;
521
+ order: number; // 1-based teaching order
522
+ name: string;
523
+ product_completion: string;
524
+ node_ids: string[]; // nodes of this phase, already in teaching order
508
525
  }
509
526
 
510
527
  type FeedEdge = {
@@ -640,19 +657,26 @@ const feed = emitCurriculumFeed(graph, {
640
657
  });
641
658
 
642
659
  // Returns CurriculumFeed with:
643
- // - learning_nodes[] — unified node format (concept | skill | product_step)
660
+ // - learning_nodes[] — unified node format (concept | skill | product_step), in teaching order when phases[] is non-empty
644
661
  // - dependency_edges[] — knowledge (prerequisite) or task (build order) edges
645
- // - suggested_groupings[] — feature or category groupings
646
- // - Each node has: bloom_hint, depth_hint (ulo/cio/sio), keywords.new vs .prerequisite
662
+ // - suggested_groupings[] — feature or category groupings (layout hint only)
663
+ // - phases[] — development phases; when non-empty, the teaching sequence + unit structure
664
+ // - Each node has: bloom_hint, depth_hint (ulo/cio/sio), keywords.new vs .prerequisite,
665
+ // introduce_aspect (new/advanced/preview), user_visible_deliverable,
666
+ // depth_variants + depth_scaffold_candidates + is_core (depth-reconcile inputs)
647
667
  ```
648
668
 
649
669
  **Key behaviors:**
650
- - **Hybrid graphs**: concepts emitted first (prerequisite-first), then project steps; hybrid links carry depth hint onto step nodes; `estimated_prereq_minutes` accumulated per concept node
670
+ - **Teaching-order emission (contract, 2026-09-18):** when a hybrid graph carries `phases[]`, the `nodes` array follows the **phase teaching sequence** — the order in the file IS the order in the classroom. The former "concepts emitted first, then steps" array layout is ABOLISHED: it contradicted phase order, fabricated backwards prerequisite edges, and caused the planner's "Teaching-order violation" failure (see postmortem 2026-09-17 §9)
671
+ - **No fabricated backwards edges:** when a keyword consumer sits in an EARLIER phase than the concept's anchor teach (and no preview covers it), the emitter does NOT invent a dependency edge — it records a drift **warning** instead (`hybrid link drift: …`); the host decides, the emitter reports
672
+ - **Overtake guard:** a product step must never become the introducer of a concept's vocabulary; the first appearance of a keyword belongs to the concept (or its preview node) that teaches it
673
+ - **Preview priming (aspect `preview`, kit ≥0.3.0):** a phase may declare a light awareness pass for a concept whose anchor teach lives in a LATER phase — emitted as node `<cid>__PREVxx` with depth `ulo`, bloom `Understand`, ~25% minutes (min 5), `keywords.all` (making it the legitimate vocabulary introducer), no prerequisite edges, no scaffolding. Five fail-closed emission rules: unknown concept, already-introduced concept, duplicate preview, no anchor anywhere, anchor not in a later phase
651
674
  - **Knowledge graphs**: concepts + prerequisite edges + category groupings
652
675
  - **Project graphs**: features → steps + depends_on edges + feature groupings
653
676
  - **Pass-through**: if input already has `learning_nodes[]`, validates and returns as-is
654
677
  - **Legacy rejection**: throws descriptive error if graph has `implementation.tasks` but no `features[].steps` (old knowledge-tree format)
655
- - **New/prerequisite keywords**: computed in emission order — first appearance = new, seen before = prerequisite
678
+ - **New/prerequisite keywords**: computed in **teaching order** (phase sequence when phases exist, array order otherwise) — first appearance = new, seen before = prerequisite. Anchoring keywords to array position instead of teaching order is the exact assumption that caused the 2026-09-17 incident
679
+ - **Fail-closed validation**: output is validated before return — duplicate IDs, unresolvable edges, self-loops, non-empty, **and the teaching-order invariant**: when phases define the sequence, a prerequisite must live in the same or an EARLIER phase than its consumer (a violation throws at emission, never defers to the planner)
656
680
 
657
681
  ### Parsers
658
682
 
@@ -723,8 +747,15 @@ STEP 9: Feed Emission
723
747
  → Convert project_graph → FeedNode[] (kind: product_step) + FeatureGroupings
724
748
  → Convert knowledge_graph → FeedNode[] (kind: concept) + CategoryGroupings
725
749
  → Convert hybrid_graph → combined nodes + knowledge/task edges + hybrid link depth hints
726
- → Compute new/prerequisite keywords in emission order
727
- → Validate: fail-closed (duplicate IDs, edge resolution, self-loops, non-empty)
750
+ → Project steps: project outcome.user_visible onto user_visible_deliverable (checkpoint candidate)
751
+ → Concept nodes: emit depth_variants (ULO ≤ CIO ≤ SIO minutes) + depth_scaffold_candidates + is_core
752
+ → Teaching order: when phases[] exist, nodes are emitted in phase sequence; new/prerequisite
753
+ keywords computed in TEACHING order (first appearance = new), never array position
754
+ → Preview priming: phase-declared __PREVxx awareness nodes carry keywords.all (legitimate
755
+ vocabulary introducer) without fabricating prerequisite edges
756
+ → Validate: fail-closed (duplicate IDs, edge resolution, self-loops, non-empty, duplicate
757
+ phase ids, and the teaching-order invariant: a prerequisite must live in the same or an
758
+ EARLIER phase than its consumer — a backwards edge throws at emission, never in the planner)
728
759
  ```
729
760
 
730
761
  ### Knowledge Graph Pipeline (Concept-Driven)
@@ -949,7 +980,7 @@ import {
949
980
  ProjectGraphSchema, KnowledgeGraphSchema, HybridGraphSchema,
950
981
  DomainProfileSchema, ConceptMappingSchema, AssembledRoadmapSchema,
951
982
  KnowledgeConceptSchema, KnowledgeLearningPathStepSchema,
952
- CurriculumFeedSchema, FeedNodeSchema, FeedEdgeSchema, FeedGroupingSchema,
983
+ CurriculumFeedSchema, FeedNodeSchema, FeedEdgeSchema, FeedGroupingSchema, FeedPhaseSchema,
953
984
  } from '@thanh01.pmt/domain-kit';
954
985
 
955
986
  // Roadmap assembly
@@ -29,6 +29,36 @@ var FeedNodeSchema = z.object({
29
29
  references: z.array(z.object({ file: z.string().min(1), evidence: z.string().default("") })).default([]),
30
30
  feature_id: z.string().nullable().default(null),
31
31
  concept_ref: z.string().nullable().default(null),
32
+ // P52/T2.1: outcome.user_visible projected from the ProjectGraph step — the
33
+ // tangible checkpoint the session-cutting planner aims for (empty when the
34
+ // step declares no user-visible result). Concepts carry '' by default.
35
+ user_visible_deliverable: z.string().default(""),
36
+ // P52/T3.1 — depth-reconcile inputs (optional/defaulted so old feeds
37
+ // validate unchanged):
38
+ // • depth_variants: minutes to teach this node at each depth level.
39
+ // ULO (know-it-exists) ≤ CIO (mechanism) ≤ SIO (implementation). All 3
40
+ // required so a downgrade never turns an anchor teach into a zero.
41
+ // • depth_scaffold_candidates: parallel to scaffold_candidates but
42
+ // acts on DEPTH (e.g. SIO→CIO) instead of lesson time.
43
+ // • is_core: concept is a Master-Tree core concept — reconciler must
44
+ // never downgrade it; escalate instead.
45
+ depth_variants: z.object({ ulo: z.number().int().nonnegative(), cio: z.number().int().nonnegative(), sio: z.number().int().nonnegative() }).optional(),
46
+ depth_scaffold_candidates: z.array(z.object({
47
+ from_depth: z.enum(["ulo", "cio", "sio"]),
48
+ to_depth: z.enum(["ulo", "cio", "sio"]),
49
+ minutes_saved: z.number().int().nonnegative(),
50
+ reason: z.string().default("")
51
+ })).optional(),
52
+ is_core: z.boolean().default(false),
53
+ // Depth layer text (optional, additive — old feeds validate unchanged).
54
+ // Carries the ULO/CIO/SIO authored text from the KnowledgeGraph concept
55
+ // so downstream consumers (KX generator) can inject depth-appropriate
56
+ // material into their prompts without a second LLM call.
57
+ depth_context: z.object({
58
+ ulo: z.string().default(""),
59
+ cio: z.string().default(""),
60
+ sio: z.array(z.string()).default([])
61
+ }).optional(),
32
62
  // Progressive-completion bookkeeping (feed v2, additive):
33
63
  // phase_id = development phase that introduces/uses this node;
34
64
  // introduce_aspect = how the phase teaches a concept node (first intro, advanced
@@ -113,5 +143,5 @@ function validateCurriculumFeed(feed) {
113
143
  }
114
144
 
115
145
  export { CurriculumFeedSchema, FeedEdgeSchema, FeedGroupingSchema, FeedKeywordsSchema, FeedNodeSchema, FeedPhaseSchema, FeedScaffoldCandidateSchema, validateCurriculumFeed };
116
- //# sourceMappingURL=chunk-MSRKUZLY.mjs.map
117
- //# sourceMappingURL=chunk-MSRKUZLY.mjs.map
146
+ //# sourceMappingURL=chunk-E4GCCWJO.mjs.map
147
+ //# sourceMappingURL=chunk-E4GCCWJO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemas/curriculumFeedSchema.ts"],"names":[],"mappings":"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","file":"chunk-E4GCCWJO.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 // P52/T2.1: outcome.user_visible projected from the ProjectGraph step — the\n // tangible checkpoint the session-cutting planner aims for (empty when the\n // step declares no user-visible result). Concepts carry '' by default.\n user_visible_deliverable: z.string().default(''),\n // P52/T3.1 — depth-reconcile inputs (optional/defaulted so old feeds\n // validate unchanged):\n // • depth_variants: minutes to teach this node at each depth level.\n // ULO (know-it-exists) ≤ CIO (mechanism) ≤ SIO (implementation). All 3\n // required so a downgrade never turns an anchor teach into a zero.\n // • depth_scaffold_candidates: parallel to scaffold_candidates but\n // acts on DEPTH (e.g. SIO→CIO) instead of lesson time.\n // • is_core: concept is a Master-Tree core concept — reconciler must\n // never downgrade it; escalate instead.\n depth_variants: z.object({ ulo: z.number().int().nonnegative(), cio: z.number().int().nonnegative(), sio: z.number().int().nonnegative() }).optional(),\n depth_scaffold_candidates: z.array(z.object({\n from_depth: z.enum(['ulo', 'cio', 'sio']),\n to_depth: z.enum(['ulo', 'cio', 'sio']),\n minutes_saved: z.number().int().nonnegative(),\n reason: z.string().default(''),\n })).optional(),\n is_core: z.boolean().default(false),\n // Depth layer text (optional, additive — old feeds validate unchanged).\n // Carries the ULO/CIO/SIO authored text from the KnowledgeGraph concept\n // so downstream consumers (KX generator) can inject depth-appropriate\n // material into their prompts without a second LLM call.\n depth_context: z.object({\n ulo: z.string().default(''),\n cio: z.string().default(''),\n sio: z.array(z.string()).default([]),\n }).optional(),\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, advanced\n // revisit, or preview — a light ULO awareness pass that is NOT the introduction).\n phase_id: z.string().default(''),\n introduce_aspect: z.enum(['new', 'advanced', 'preview']).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 // Teaching-order invariant (2026-09-17 incident): when phases define the\n // teaching sequence, a prerequisite must live in the same or an EARLIER\n // phase than its consumer. Without this check a self-contradictory feed\n // (backwards phase-crossing edge) sailed through emission and only exploded\n // much later inside the planner as \"Teaching-order violation in session ...\"\n // — far from the constructor that produced the contradiction.\n if (parsed.phases.length > 0) {\n const phaseIndexOf = new Map<string, number>();\n parsed.phases.forEach((p, i) => {\n for (const id of p.node_ids) phaseIndexOf.set(id, i);\n });\n for (const e of parsed.dependency_edges) {\n const fromIdx = phaseIndexOf.get(e.from);\n const toIdx = phaseIndexOf.get(e.to);\n if (fromIdx === undefined || toIdx === undefined) continue; // node outside the phase sequence\n if (fromIdx > toIdx) {\n throw new Error(\n 'curriculum feed teaching-order violation: prerequisite ' + e.from +\n ' (phase ' + (fromIdx + 1) + ') is scheduled AFTER its consumer ' + e.to +\n ' (phase ' + (toIdx + 1) + ')',\n );\n }\n }\n }\n return parsed;\n}\n"]}
@@ -1,8 +1,8 @@
1
- import { emitCurriculumFeed } from './chunk-LKSVTRQE.mjs';
1
+ import { emitCurriculumFeed } from './chunk-TWKIVUTQ.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
4
  import { detectDomainProfile } from './chunk-BL5NBKPH.mjs';
5
- import { extractScaffold, extractProjectOverview, extractFeatureStepsBatched, extractFeatureSteps, verifyProjectGraph, escalateAndMapConcepts, generateKnowledgeGraph, generateHybridGraph, createLlmClient, llmChatJson } from './chunk-Y7MRFFDJ.mjs';
5
+ import { extractScaffold, extractProjectOverview, extractFeatureStepsBatched, extractFeatureSteps, verifyProjectGraph, escalateAndMapConcepts, generateKnowledgeGraph, generateHybridGraph, createLlmClient, llmChatJson } from './chunk-TYXSJUQU.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';
@@ -597,7 +597,7 @@ async function runDomainPipeline(options) {
597
597
  embeddings: options.embeddings,
598
598
  onProgress: options.onProgress
599
599
  });
600
- const { emitCurriculumFeed: emitCurriculumFeed2 } = await import('./curriculumFeedEmitter-FYAWMPE6.mjs');
600
+ const { emitCurriculumFeed: emitCurriculumFeed2 } = await import('./curriculumFeedEmitter-T7NUBLAM.mjs');
601
601
  const curriculumFeed = emitCurriculumFeed2(projectResult.projectGraph, {
602
602
  warnings
603
603
  });
@@ -611,5 +611,5 @@ async function runDomainPipeline(options) {
611
611
  }
612
612
 
613
613
  export { runDomainPipeline, runHybridGraphPipeline, runKnowledgeGraphPipeline, runProjectGraphPipeline };
614
- //# sourceMappingURL=chunk-MCHHEBH3.mjs.map
615
- //# sourceMappingURL=chunk-MCHHEBH3.mjs.map
614
+ //# sourceMappingURL=chunk-G7HLFMD2.mjs.map
615
+ //# sourceMappingURL=chunk-G7HLFMD2.mjs.map
@@ -1 +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","emitCurriculumFeed"],"mappings":"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","file":"chunk-MCHHEBH3.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 } 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): 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 = 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 } 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}\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\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,\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 });\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 });\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,\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, llmConfig,\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 });\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 };\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';\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 });\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 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 });\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 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}\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) {\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 });\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 warnings.push('Hybrid learning mode requested but repoDir was not provided — falling back to concept-driven knowledge graph pipeline');\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 });\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\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\n const { emitCurriculumFeed } = await import('../feed/curriculumFeedEmitter');\n const curriculumFeed = emitCurriculumFeed(projectResult.projectGraph, {\n warnings,\n });\n\n return {\n domainProfile,\n graphType: 'project_graph',\n curriculumFeed,\n projectResult,\n warnings,\n };\n}\n"]}
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","emitCurriculumFeed"],"mappings":";;;;;;;;;;;;;AAsBA,eAAsB,kBAAA,CACpB,SAAA,EACA,IAAA,EACA,SAAA,EACA,SAAA,EAC8B;AAE9B,EAAA,IAAI,SAAA,CAAU,UAAU,EAAA,EAAI;AAC1B,IAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,yBAAA,EAA0B;AAAA,EACrE;AAEA,EAAA,MAAM,MAAA,GAAS,gBAAgB,SAAS,CAAA;AAGxC,EAAA,MAAM,SAAA,GAAY,cAAc,SAAS,CAAA;AAEzC,EAAA,MAAM,YAAA,GACJ,wyBAAA;AAcF,EAAA,MAAM,UAAA,GACJ,iBAAiB,IAAI;AAAA,YAAA,EACJ,SAAS;;AAAA,WAAA,EACV,UAAU,MAAM,CAAA;AAAA,EAAa,SAAS;;AAAA,wDAAA,CAAA;AAIxD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,WAAA,CAAY,MAAA,EAAQ,cAAc,UAAA,EAAY;AAAA,MACjE,WAAA,EAAa,GAAA;AAAA,MACb,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,GAAI,MAAA,CAAO,WAAuB,EAAC;AACjF,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,EAAE,CAAA;AAG/C,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,SAAS,CAAA;AACjC,IAAA,MAAM,gBAAgB,QAAA,CAAS,MAAA,CAAO,OAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAC,CAAA;AAEzD,IAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAE9B,MAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,sCAAA,EAAuC;AAAA,IAClF;AAEA,IAAA,OAAO,EAAE,QAAA,EAAU,aAAA,EAAe,SAAA,EAAU;AAAA,EAC9C,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,kCAAA,EAAqC,GAAG,CAAA,kBAAA,CAAoB,CAAA;AACzE,IAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,CAAA,YAAA,EAAe,GAAG,CAAA,CAAA,EAAG;AAAA,EAChE;AACF;AAMA,SAAS,cAAc,SAAA,EAA6B;AAClD,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAsB;AAExC,EAAA,KAAA,MAAW,MAAM,SAAA,EAAW;AAC1B,IAAA,MAAM,KAAA,GAAQ,EAAA,CAAG,KAAA,CAAM,GAAG,CAAA;AAC1B,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,GAAI,QAAA;AAC9D,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACnC,IAAA,IAAI,CAAC,MAAM,GAAA,CAAI,GAAG,GAAG,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,EAAE,CAAA;AACtC,IAAA,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,CAAG,IAAA,CAAK,IAAI,CAAA;AAAA,EAC3B;AAEA,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,KAAA,EAAO;AAChC,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,CAAA,CAAG,CAAA;AACpB,IAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,IAAA,EAAK,EAAG;AAC5B,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,CAAC,CAAA,CAAE,CAAA;AAAA,IACrB;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;ACjEO,SAAS,kBAAA,CACd,KACA,OAAA,EAKU;AACV,EAAA,MAAM,WAAA,GAA4C,CAAC,UAAU,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,MAAM,MAAM,CAAA;AACpI,EAAA,MAAM,QAAA,GAAgC,EAAA;AAGtC,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,GAAA,EAAK,WAAA,EAAa,QAAQ,CAAA;AACzD,EAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,OAAO,QAAA;AAGhC,EAAA,OAAO,oBAAA,CAAqB,GAAA,EAAK,WAAA,EAAa,QAA2B,CAAA;AAC3E;AAMA,SAAS,aAAA,CAAc,GAAA,EAAa,WAAA,EAAuB,QAAA,EAA4B;AACrF,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,SAAS,mDAAA,EAAqD;AAAA,MACxE,GAAA,EAAK,GAAA;AAAA,MACL,QAAA,EAAU,OAAA;AAAA,MACV,OAAA,EAAS,GAAA;AAAA,MACT,WAAW,IAAA,GAAO;AAAA,KACnB,CAAA;AACD,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,WAAA,CAAY,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AAC5D,IAAA,OAAO,GAAA,CACJ,KAAA,CAAM,IAAI,CAAA,CACV,MAAA,CAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAC9B,MAAA,CAAO,CAAA,IAAA,KAAQ,OAAO,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA,CACtD,KAAA,CAAM,CAAA,EAAG,QAAQ,CAAA,CACjB,GAAA,CAAI,CAAA,GAAA,KAAO,IAAA,CAAK,GAAA,EAAK,GAAG,CAAC,CAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAKA,SAAS,oBAAA,CACP,GAAA,EACA,WAAA,EACA,QAAA,EACA,QAAA,EACU;AACV,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAgB;AAAA,IAClC,cAAA;AAAA,IAAgB,QAAA;AAAA,IAAU,MAAA;AAAA,IAAQ,MAAA;AAAA,IAAQ,OAAA;AAAA,IAAS,MAAA;AAAA,IACnD,aAAA;AAAA,IAAe,OAAA;AAAA,IAAS,MAAA;AAAA,IAAQ,OAAA;AAAA,IAAS,SAAA;AAAA,IACzC,MAAA;AAAA,IAAQ,OAAA;AAAA,IAAS,MAAA;AAAA,IAAQ,QAAA;AAAA,IAAU,SAAA;AAAA,IAAW;AAAA,GAC/C,CAAA;AACD,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,WAAA,CAAY,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AAC5D,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,SAAS,KAAK,UAAA,EAAoB;AAChC,IAAA,IAAI,MAAA,CAAO,UAAU,QAAA,EAAU;AAC/B,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,WAAA,CAAY,UAAA,EAAY,EAAE,aAAA,EAAe,MAAM,CAAA;AAAA,IAC3D,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AACA,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,MAAA,CAAO,UAAU,QAAA,EAAU;AAC/B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,EAAY,KAAA,CAAM,IAAI,CAAA;AAC5C,MAAA,IAAI,KAAA,CAAM,aAAY,EAAG;AACvB,QAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AAC5B,UAAA,IAAA,CAAK,QAAQ,CAAA;AAAA,QACf;AAAA,MACF,CAAA,MAAA,IAAW,KAAA,CAAM,MAAA,EAAO,EAAG;AACzB,QAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,KAAA,CAAM,IAAI,EAAE,WAAA,EAAY;AAC5C,QAAA,IAAI,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,EAAG;AACnB,UAAA,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAA,CAAK,GAAG,CAAA;AACR,EAAA,OAAO,MAAA;AACT;AA6CO,SAAS,2BAAA,CACd,GAAA,EACA,aAAA,EACA,QAAA,GAAmB,GAAA,EACE;AACrB,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAoB;AACzC,EAAA,IAAI,UAAA,GAAa,CAAA;AAEjB,EAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AACnC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,EAAK,OAAO,CAAA;AAClC,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC9C,MAAA,IAAI,UAAA,GAAa,OAAA,CAAQ,MAAA,GAAS,QAAA,EAAU;AAC1C,QAAA,MAAM,YAAY,QAAA,GAAW,UAAA;AAC7B,QAAA,IAAI,YAAY,GAAA,EAAK;AACnB,UAAA,QAAA,CAAS,IAAI,OAAA,EAAS,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,SAAS,CAAC,CAAA;AACjD,UAAA,UAAA,IAAc,SAAA;AAAA,QAChB;AACA,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,GAAA,CAAI,SAAS,OAAO,CAAA;AAC7B,MAAA,UAAA,IAAc,OAAA,CAAQ,MAAA;AAAA,IACxB,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;AAKO,SAAS,sBAAsB,SAAA,EAA6B;AACjE,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,EAAA,KAAA,MAAW,MAAM,SAAA,EAAW;AAC1B,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,EAAE,CAAA,CAAE,WAAA,EAAY;AACpC,IAAA,IAAI,IAAA,GAAO,SAAA;AACX,IAAA,IAAI,GAAA,KAAQ,UAAU,IAAA,GAAO,OAAA;AAAA,SAAA,IACpB,GAAA,KAAQ,KAAA,IAAS,GAAA,KAAQ,MAAA,EAAQ,IAAA,GAAO,YAAA;AAAA,SAAA,IACxC,GAAA,KAAQ,KAAA,IAAS,GAAA,KAAQ,MAAA,EAAQ,IAAA,GAAO,YAAA;AAAA,SAAA,IACxC,GAAA,KAAQ,OAAO,IAAA,GAAO,QAAA;AAAA,SAAA,IACtB,GAAA,KAAQ,UAAU,GAAA,KAAQ,MAAA,IAAU,QAAQ,IAAA,IAAQ,GAAA,KAAQ,MAAM,IAAA,GAAO,KAAA;AAAA,SAAA,IACzE,GAAA,KAAQ,KAAA,IAAS,GAAA,KAAQ,MAAA,EAAQ,IAAA,GAAO,QAAA;AACjD,IAAA,MAAA,CAAO,IAAI,IAAA,EAAA,CAAO,MAAA,CAAO,IAAI,IAAI,CAAA,IAAK,KAAK,CAAC,CAAA;AAAA,EAC9C;AAEA,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,IAAI,OAAA,GAAU,SAAA;AACd,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,MAAA,EAAQ;AAClC,IAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,MAAA,QAAA,GAAW,KAAA;AACX,MAAA,OAAA,GAAU,IAAA;AAAA,IACZ;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;ACzLA,eAAsB,wBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,OAAA,EAAS,IAAA,EAAM,WAAW,SAAA,EAAW,UAAA,EAAY,YAAW,GAAI,OAAA;AAExE,EAAA,MAAM,GAAA,GAAM,CAAC,IAAA,EAAc,GAAA,KAAgB;AACzC,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,EAAI,IAAI,CAAA,EAAA,EAAK,GAAG,CAAA,CAAE,CAAA;AAC9B,IAAA,UAAA,GAAa,MAAM,GAAG,CAAA;AAAA,EACxB,CAAA;AAGA,EAAA,GAAA,CAAI,UAAU,oCAAoC,CAAA;AAElD,EAAA,MAAM,YAAA,GAAe,mBAAmB,OAAO,CAAA;AAC/C,EAAA,MAAM,cAAc,YAAA,CAAa,GAAA,CAAI,QAAMA,QAAAA,CAAS,OAAA,EAAS,EAAE,CAAC,CAAA;AAChE,EAAA,GAAA,CAAI,QAAA,EAAU,CAAA,MAAA,EAAS,WAAA,CAAY,MAAM,CAAA,2BAAA,CAA6B,CAAA;AAGtE,EAAA,GAAA,CAAI,UAAU,uDAAuD,CAAA;AAErE,EAAA,MAAM,EAAE,QAAA,EAAU,aAAA,EAAe,SAAA,KAAc,MAAM,kBAAA;AAAA,IACnD,WAAA;AAAA,IAAa,IAAA;AAAA,IAAM,SAAA;AAAA,IAAW;AAAA,GAChC;AACA,EAAA,GAAA,CAAI,QAAA,EAAU,CAAA,aAAA,EAAgB,aAAA,CAAc,MAAM,CAAA,CAAA,EAAI,WAAA,CAAY,MAAM,CAAA,QAAA,EAAW,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAG5G,EAAA,GAAA,CAAI,UAAU,uCAAuC,CAAA;AAErD,EAAA,MAAM,eAAA,GAAkB,2BAAA,CAA4B,OAAA,EAAS,aAAa,CAAA;AAC1E,EAAA,MAAM,SAAA,GAAY,aAAA;AAClB,EAAA,MAAM,WAAA,GAAc,sBAAsB,SAAS,CAAA;AACnD,EAAA,GAAA,CAAI,QAAA,EAAU,qBAAqB,WAAW,CAAA,EAAA,EAAK,UAAU,MAAM,CAAA,eAAA,EAAkB,eAAA,CAAgB,IAAI,CAAA,cAAA,CAAgB,CAAA;AAGzH,EAAA,GAAA,CAAI,UAAU,iDAAiD,CAAA;AAE/D,EAAA,MAAM,kBAAmC,EAAC;AAC1C,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,OAAO,CAAA,IAAK,eAAA,EAAiB;AAChD,IAAA,MAAM,QAAA,GAAW,OAAA;AACjB,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC/B,MAAA,eAAA,CAAgB,IAAA,CAAK,cAAA,CAAe,QAAA,EAAU,OAAO,CAAC,CAAA;AAAA,IACxD,WAAW,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,IAAK,SAAS,QAAA,CAAS,MAAM,CAAA,IAAK,QAAA,CAAS,SAAS,KAAK,CAAA,IAAK,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AACzH,MAAA,eAAA,CAAgB,IAAA,CAAK,WAAA,CAAY,QAAA,EAAU,OAAO,CAAC,CAAA;AAAA,IACrD,CAAA,MAAA,IAAW,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,EAAG;AACnC,MAAA,eAAA,CAAgB,IAAA,CAAK,eAAA,CAAgB,QAAA,EAAU,OAAO,CAAC,CAAA;AAAA,IACzD,WAAW,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,IAAK,SAAS,QAAA,CAAS,MAAM,CAAA,IAAK,QAAA,CAAS,SAAS,IAAI,CAAA,IAAK,QAAA,CAAS,QAAA,CAAS,IAAI,CAAA,EAAG;AACvH,MAAA,eAAA,CAAgB,IAAA,CAAK,YAAA,CAAa,QAAA,EAAU,OAAO,CAAC,CAAA;AAAA,IACtD;AAAA,EACF;AAGA,EAAA,IAAI,aAAA;AACJ,EAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,IAAA,aAAA,GAAgB,kBAAkB,eAAA,CAAgB,MAAA,CAAO,CAAC,CAAA,KAA6B,mBAAA,IAAuB,CAAC,CAAC,CAAA;AAAA,EAClH,CAAA,MAAA,IAAW,WAAA,KAAgB,YAAA,IAAgB,WAAA,KAAgB,YAAA,EAAc;AACvE,IAAA,aAAA,GAAgB,cAAA,CAAe,eAAA,CAAgB,MAAA,CAAO,CAAC,MAA0B,EAAE,YAAA,IAAgB,CAAA,CAAA,IAAM,EAAE,mBAAA,IAAuB,CAAA,CAAA,IAAM,EAAE,iBAAA,IAAqB,EAAE,CAAC,CAAA;AAAA,EACpK,CAAA,MAAA,IAAW,gBAAgB,QAAA,EAAU;AACnC,IAAA,aAAA,GAAgB,mBAAmB,eAAA,CAAgB,MAAA,CAAO,CAAC,CAAA,KAA8B,YAAA,IAAgB,CAAC,CAAC,CAAA;AAAA,EAC7G,CAAA,MAAO;AACL,IAAA,aAAA,GAAgB,eAAA,CAAgB,eAAA,CAAgB,MAAA,CAAO,CAAC,CAAA,KAA2B,gBAAA,IAAoB,CAAA,IAAK,EAAE,YAAA,IAAgB,CAAA,CAAA,IAAM,EAAE,mBAAA,IAAuB,EAAE,CAAC,CAAA;AAAA,EAClK;AAGA,EAAA,GAAA,CAAI,UAAU,0CAA0C,CAAA;AAExD,EAAA,MAAM,WAAA,GAAc,gBAAgB,aAAa,CAAA;AACjD,EAAA,GAAA,CAAI,QAAA,EAAU,CAAA,UAAA,EAAa,WAAA,CAAY,MAAM,CAAA,SAAA,CAAW,CAAA;AAGxD,EAAA,GAAA,CAAI,UAAU,2BAA2B,CAAA;AAEzC,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,QAAA,EAAU,WAAA,CAAY,GAAA,CAAI,CAAA,EAAA,MAAO;AAAA,MAC/B,MAAM,EAAA,CAAG,OAAA;AAAA,MACT,MAAM,EAAA,CAAG,MAAA;AAAA,MACT,YAAA,EAAc;AAAA,KAChB,CAAE;AAAA,GACJ;AAGA,EAAA,GAAA,CAAI,UAAU,6EAA6E,CAAA;AAG3F,EAAA,GAAA,CAAI,aAAa,+CAA+C,CAAA;AAChE,EAAA,MAAM,eAAA,GAAkB,MAAM,eAAA,CAAgB;AAAA,IAC5C,IAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA,EAAU,SAAA;AAAA,IACV;AAAA,GACD,CAAA;AAGD,EAAA,GAAA,CAAI,aAAa,gDAAgD,CAAA;AACjE,EAAA,MAAM,QAAA,GAAW,MAAM,sBAAA,CAAuB;AAAA,IAC5C,IAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA,eAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACD,CAAA;AAGD,EAAA,MAAM,UAAU,QAAA,CAAS,OAAA;AACzB,EAAA,MAAM,OAAA,GAA4D;AAAA,IAChE,EAAA,EAAI,OAAA;AAAA,IACJ,QAAA,EAAU,CAAA;AAAA,IACV,IAAA,EAAM,6DAAA;AAAA,IACN,WAAA,EAAa,2EAAA;AAAA,IACb,OAAO,EAAC;AAAA,IACR,WAAW,EAAC;AAAA,IACZ,UAAU,CAAC,iBAAA,EAAmB,YAAA,EAAc,mBAAA,EAAqB,gBAAgB,KAAK,CAAA;AAAA,IACtF,gBAAA,EAAkB,MAAA;AAAA,IAClB,QAAA,EAAU,KAAA;AAAA,IACV,MAAA,EAAQ,6DAAA;AAAA,IACR,OAAA,EAAS,EAAE,YAAA,EAAc,2BAAA,EAA6B,WAAW,uBAAA,EAAwB;AAAA,IACzF,UAAA,EAAY,CAAC,4BAAA,EAA8B,0BAA0B,CAAA;AAAA,IACrE,iBAAiB,EAAC;AAAA,IAClB,eAAe,EAAC;AAAA,IAChB,MAAA,EAAQ,EAAE,iBAAA,EAAmB,EAAA,EAAI,YAAY,KAAA;AAAM,GACrD;AAGA,EAAA,IAAI,eAA0B,EAAC;AAC/B,EAAA,IAAI,eAAA,EAAiB;AACnB,IAAA,MAAM,aAAA,GAAgB,CAAC,OAAA,EAAS,GAAI,eAAA,CAAgB,KAAA,IAAS,EAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,MAAO;AAAA,MAC/E,GAAG,CAAA;AAAA,MACH,EAAA,EAAI,CAAA,IAAA,EAAO,CAAA,GAAI,CAAC,CAAA,CAAA;AAAA,MAChB,UAAU,CAAA,GAAI;AAAA,KAChB,CAAE,CAAA;AACF,IAAA,YAAA,CAAa,IAAA,CAAK;AAAA,MAChB,GAAG,eAAA;AAAA,MACH,EAAA,EAAI,IAAA;AAAA,MACJ,IAAA,EAAM,oBAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,YAAA,CAAa,IAAA,CAAK;AAAA,MAChB,EAAA,EAAI,IAAA;AAAA,MACJ,IAAA,EAAM,oBAAA;AAAA,MACN,WAAA,EAAa,gDAAA;AAAA,MACb,KAAA,EAAO,CAAC,OAAO;AAAA,KACL,CAAA;AAAA,EACd;AAGA,EAAA,MAAM,gBAAA,GAAoB,OAAA,EAAS,QAAA,IAAY,EAAC;AAChD,EAAA,YAAA,GAAe,CAAC,GAAG,YAAA,EAAc,GAAG,gBAAgB,CAAA;AAGpD,EAAA,GAAA,CAAI,WAAA,EAAa,CAAA,qBAAA,EAAwB,gBAAA,CAAiB,MAAM,CAAA,YAAA,CAAc,CAAA;AAE9E,EAAA,MAAM,gBAAgB,gBAAA,CAAiB,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,IAAI,CAAA;AAChE,EAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAAG;AAC5B,IAAA,IAAI;AACF,MAAA,MAAM,eAAe,MAAM,0BAAA;AAAA,QACzB,IAAA;AAAA,QAAM,SAAA;AAAA,QAAW,WAAA;AAAA,QAAa,eAAA;AAAA,QAAiB,aAAA;AAAA,QAAe;AAAA,OAChE;AACA,MAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AACnC,QAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,GAAA,CAAI,OAAA,CAAQ,MAAM,EAAE,CAAA;AAC/C,QAAA,IAAI,KAAA,UAAe,KAAA,GAAQ,KAAA;AAAA,MAC7B;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,GAAA,CAAI,WAAA,EAAa,CAAA,yBAAA,EAA4B,GAAG,CAAA,iCAAA,CAAmC,CAAA;AACnF,MAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AACnC,QAAA,IAAI;AACF,UAAA,MAAM,KAAA,GAAQ,MAAM,mBAAA,CAAoB;AAAA,YACtC,IAAA;AAAA,YAAM,SAAA;AAAA,YAAW,WAAA;AAAA,YAAa,eAAA;AAAA,YAAiB,OAAA;AAAA,YAAS;AAAA,WACzD,CAAA;AACD,UAAA,OAAA,CAAQ,KAAA,GAAQ,KAAA;AAAA,QAClB,SAAS,CAAA,EAAG;AACV,UAAA,GAAA,CAAI,aAAa,CAAA,WAAA,EAAc,OAAA,CAAQ,EAAE,CAAA,EAAA,EAAK,CAAC,CAAA,CAAE,CAAA;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,YAAA,GAA6B;AAAA,IACjC,cAAA,EAAgB,CAAA;AAAA,IAChB,OAAA,EAAS;AAAA,MACP,EAAA,EAAK,QAAA,CAAS,OAAA,EAAqC,IAAA,EAAM,QAAA,EAAS,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,IAAK,SAAA;AAAA,MAC1G,IAAA,EAAO,QAAA,CAAS,OAAA,EAAqC,IAAA,EAAM,UAAS,IAAK,SAAA;AAAA,MACzE,OAAA,EAAS,IAAA;AAAA,MACT,OAAA,EAAS,OAAA;AAAA,MACT,YAAA,EAAc,KAAA;AAAA,MACd,QAAA,EAAY,QAAA,CAAS,OAAA,EAAqC,SAAA,IAA0B,CAAC,KAAK,CAAA;AAAA,MAC1F,UAAA,EAAY,UAAU,KAAA,CAAM,GAAG,EAAE,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM;AAClD,QAAA,MAAM,GAAA,GAAM,CAAA,CAAE,IAAA,EAAK,CAAE,WAAA,EAAY;AACjC,QAAA,IAAI,KAAK,GAAA,CAAI,GAAG,IAAI,CAAC,CAAA,CAAE,MAAM,CAAA;AAC7B,QAAA,OAAO,GAAA;AAAA,MACT,CAAA,EAAG,EAA8B,CAAA;AAAA,MACjC,YAAA,EAAe,QAAA,CAAS,YAAA,EAA0C,MAAA,IAAsB;AAAC,KAC3F;AAAA,IACA,OAAA,EAAS;AAAA,MACP,KAAA,EAAQ,OAAA,EAAS,KAAA,IAAwD,EAAC;AAAA,MAC1E,KAAA,EAAQ,OAAA,EAAS,KAAA,IAAoD,EAAC;AAAA,MACtE,QAAA,EAAW,OAAA,EAAS,aAAA,IAA4H,EAAC;AAAA,MACjJ,cAAc,EAAC;AAAA,MACf,kBAAA,EAAqB,OAAA,EAAS,kBAAA,IAAwL,EAAC;AAAA,MACvN,OAAA,EAAS,MAAA,CAAO,OAAA,EAAS,OAAA,IAAW,EAAE,CAAA;AAAA,MACtC,iBAAA,EAAmB,MAAA,CAAO,OAAA,EAAS,iBAAA,IAAqB,EAAE,CAAA;AAAA,MAC1D,aAAA,EAAgB,OAAA,EAAS,aAAA,IAA8B;AAAC,KAC1D;AAAA,IACA,QAAA,EAAU,YAAA;AAAA,IACV,cAAc,EAAC;AAAA,IACf,cAAA,EAAgB;AAAA,MACd,OAAO;AAAC,KACV;AAAA,IACA,cAAc,EAAC;AAAA,IACf,WAAW;AAAC,GACd;AAGA,EAAA,GAAA,CAAI,UAAU,gDAAgD,CAAA;AAE9D,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAe,cAAA,EAAe,GAAI,mBAAmB,YAAA,EAAc;AAAA,IAChF,OAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAA,GAAA,CAAI,QAAA,EAAU,CAAA,uBAAA,EAA0B,cAAA,CAAe,MAAM,CAAA,qBAAA,CAAuB,CAAA;AAGpF,EAAA,GAAA,CAAI,UAAU,4CAA4C,CAAA;AAE1D,EAAA,MAAM,eAAA,GAAkB,MAAM,sBAAA,CAAuB;AAAA,IACnD,YAAA,EAAc,aAAA;AAAA,IACd,eAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAA,GAAA,CAAI,QAAA,EAAU,CAAA,0BAAA,EAA6B,eAAA,CAAgB,IAAI,CAAA,gBAAA,CAAkB,CAAA;AAGjF,EAAA,KAAA,MAAW,OAAA,IAAW,aAAA,CAAc,QAAA,IAAY,EAAC,EAAG;AAClD,IAAA,MAAM,GAAA,GAAM,QAAQ,EAAA,IAAM,EAAA;AAC1B,IAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,GAAA,CAAI,GAAG,KAAK,EAAC;AAC/C,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,CAAQ,KAAA,IAAS,EAAC,EAAG;AACtC,MAAA,MAAM,YAAA,GAAe,SAAA,CAClB,MAAA,CAAO,CAAA,EAAA,KAAM;AAEZ,QAAA,MAAM,OAAA,GAAU,CAAC,GAAI,IAAA,CAAK,QAAA,IAAY,EAAC,EAAI,GAAI,IAAA,CAAK,SAAA,IAAa,EAAG,CAAA;AACpE,QAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,KAAM,GAAG,OAAO,CAAA;AAAA,MAC3C,CAAC,CAAA,CACA,GAAA,CAAI,CAAA,EAAA,KAAM,GAAG,YAAY,CAAA;AAE5B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,IAAiB,EAAC;AACxC,MAAA,IAAA,CAAK,aAAA,GAAgB,CAAC,mBAAG,IAAI,GAAA,CAAI,CAAC,GAAG,QAAA,EAAU,GAAG,YAAY,CAAC,CAAC,CAAA;AAAA,IAClE;AAAA,EACF;AAGA,EAAA,GAAA,CAAI,UAAU,+CAA+C,CAAA;AAG7D,EAAA,MAAM,cAAyB,EAAC;AAChC,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAC/B,EAAA,KAAA,MAAW,OAAA,IAAW,aAAA,CAAc,QAAA,IAAY,EAAC,EAAG;AAClD,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,CAAQ,KAAA,IAAS,EAAC,EAAG;AACtC,MAAA,KAAA,MAAW,EAAA,IAAM,CAAC,GAAI,IAAA,CAAK,QAAA,IAAY,EAAC,EAAI,GAAI,IAAA,CAAK,SAAA,IAAa,EAAG,CAAA,EAAG;AACtE,QAAA,IAAI,CAAC,MAAA,CAAO,GAAA,CAAI,EAAA,CAAG,WAAA,EAAa,CAAA,EAAG;AACjC,UAAA,MAAA,CAAO,GAAA,CAAI,EAAA,CAAG,WAAA,EAAa,CAAA;AAC3B,UAAA,WAAA,CAAY,IAAA,CAAK,EAAE,OAAA,EAAS,EAAA,EAAI,MAAA,EAAQ,UAAA,EAAY,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,CAAA,EAAK,OAAA,EAAS,4BAAA,EAA8B,CAAA;AAAA,QAC3H;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,WAAA,CAAY,GAAA,CAAI,CAAA,CAAA,KAAK,CAAC,CAAA,CAAE,OAAA,CAAQ,WAAA,EAAY,EAAG,CAAC,CAAC,CAAC,CAAA;AAC3E,EAAA,MAAM,iBAA4B,EAAC;AACnC,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AACnC,EAAA,KAAA,MAAW,MAAM,CAAC,GAAG,WAAA,EAAa,GAAG,WAAW,CAAA,EAAG;AACjD,IAAA,MAAM,GAAA,GAAM,EAAA,CAAG,OAAA,CAAQ,WAAA,EAAY;AACnC,IAAA,IAAI,CAAC,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA,EAAG;AACxB,MAAA,UAAA,CAAW,IAAI,GAAG,CAAA;AAClB,MAAA,cAAA,CAAe,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAG,KAAK,EAAE,CAAA;AAAA,IAC7C;AAAA,EACF;AAGA,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAmC;AAC9D,EAAA,KAAA,MAAW,QAAA,IAAY,eAAA,CAAgB,MAAA,EAAO,EAAG;AAC/C,IAAA,KAAA,MAAW,MAAM,QAAA,EAAU;AACzB,MAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,EAAA,CAAG,OAAO,CAAA,EAAG;AACnC,QAAA,cAAA,CAAe,GAAA,CAAI,EAAA,CAAG,OAAA,EAAS,EAAA,CAAG,KAAK,CAAA;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,gBAAA,GAAmB,MAAM,eAAA,CAAgB;AAAA,IAC7C,QAAA,EAAU,cAAA;AAAA,IACV,IAAA;AAAA,IACA,UAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAA,GAAA,CAAI,QAAA,EAAU,CAAA,UAAA,EAAa,gBAAA,CAAiB,OAAA,CAAQ,cAAc,CAAA,YAAA,EAAe,gBAAA,CAAiB,OAAA,CAAQ,cAAc,CAAA,EAAA,EAAK,gBAAA,CAAiB,OAAA,CAAQ,WAAW,CAAA,CAAA,CAAG,CAAA;AAGpK,EAAA,GAAA,CAAI,UAAU,6CAA6C,CAAA;AAE3D,EAAA,MAAM,UAAU,eAAA,CAAgB;AAAA,IAC9B,YAAA,EAAc,aAAA;AAAA,IACd,eAAA;AAAA,IACA,cAAA,EAAgB,EAAA;AAAA,IAChB,cAAA,EAAgB,IAAA;AAAA,IAChB,mBAAA,EAAqB;AAAA,GACtB,CAAA;AACD,EAAA,GAAA,CAAI,UAAU,CAAA,mBAAA,EAAsB,OAAA,CAAQ,OAAO,MAAM,CAAA,SAAA,EAAY,QAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,EAAG,MAAM,CAAA,GAAI,CAAA,CAAE,WAAW,MAAA,EAAQ,CAAC,CAAC,CAAA,WAAA,CAAa,CAAA;AAE7I,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,aAAA;AAAA,IACd,gBAAA;AAAA,IACA,OAAA;AAAA,IACA,cAAA;AAAA,IACA,QAAA,EAAU,WAAA;AAAA,IACV;AAAA,GACF;AACF;;;ACnVA,eAAsB,0BACpB,OAAA,EACkC;AAClC,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,IAAI,iBAAiB,OAAA,CAAQ,cAAA;AAE7B,EAAA,IAAI,CAAC,cAAA,IAAkB,OAAA,CAAQ,YAAA,EAAc;AAC3C,IAAA,cAAA,GAAiB,aAAA,CAAc,QAAQ,YAAY,CAAA;AAAA,EACrD;AAEA,EAAA,MAAM,gBAAA,GAAmB,OAAA,CAAQ,OAAA,IAAW,cAAA,EAAgB,QAAQ,KAAA,IAAS,kBAAA;AAC7E,EAAA,MAAM,eAAA,GAAkB,OAAA,CAAQ,MAAA,IAAU,cAAA,EAAgB,QAAQ,MAAA,IAAU,OAAA;AAC5E,EAAA,MAAM,kBAAA,GAAqB,OAAA,CAAQ,SAAA,IAAa,cAAA,EAAgB,OAAA,CAAQ,SAAA;AACxE,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,WAAA,IAAe,cAAA,EAAgB,OAAA,CAAQ,WAAA;AAErE,EAAA,MAAM,MAAA,GAAS,MAAM,sBAAA,CAAuB;AAAA,IAC1C,GAAG,OAAA;AAAA,IACH,OAAA,EAAS,gBAAA;AAAA,IACT,MAAA,EAAQ,eAAA;AAAA,IACR,SAAA,EAAW,kBAAA;AAAA,IACX,WAAA,EAAa,aAAA;AAAA,IACb;AAAA,GACD,CAAA;AAED,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,MAAA,CAAO,QAAQ,CAAA;AAGhC,EAAA,MAAM,cAAA,GAAiB,kBAAA,CAAmB,MAAA,CAAO,cAAA,EAAgB;AAAA,IAC/D;AAAA,GACD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,gBAAgB,MAAA,CAAO,cAAA;AAAA,IACvB,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAoB,MAAA,CAAO,kBAAA;AAAA,IAC3B;AAAA,GACF;AACF;;;AC1CA,eAAsB,uBACpB,OAAA,EAC+B;AAC/B,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,CAAoB,OAAO,CAAA;AAChD,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,MAAA,CAAO,QAAQ,CAAA;AAEhC,EAAA,MAAM,cAAA,GAAiB,kBAAA,CAAmB,MAAA,CAAO,WAAA,EAAa;AAAA,IAC5D;AAAA,GACD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,cAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACMA,eAAsB,kBACpB,OAAA,EAC+B;AAC/B,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,MAAM,GAAA,GAAM,CAAC,IAAA,EAAc,GAAA,KAAgB;AACzC,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,QAAA,EAAW,IAAI,CAAA,EAAA,EAAK,GAAG,CAAA,CAAE,CAAA;AACrC,IAAA,OAAA,CAAQ,UAAA,GAAa,MAAM,GAAG,CAAA;AAAA,EAChC,CAAA;AAGA,EAAA,GAAA,CAAI,WAAW,6BAA6B,CAAA;AAC5C,EAAA,MAAM,aAAA,GAAgB,oBAAoB,OAAO,CAAA;AAEjD,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,kBAAA,IAAsB,aAAA,CAAc,YAAA;AAClE,EAAA,GAAA,CAAI,WAAW,CAAA,uCAAA,EAA0C,aAAa,CAAA,aAAA,EAAgB,aAAA,CAAc,SAAS,CAAA,CAAA,CAAG,CAAA;AAGhH,EAAA,IAAI,kBAAkB,SAAA,EAAW;AAC/B,IAAA,GAAA,CAAI,WAAW,wDAAwD,CAAA;AACvE,IAAA,MAAM,eAAA,GAAkB,MAAM,yBAAA,CAA0B;AAAA,MACtD,OAAA,EAAS,QAAQ,OAAA,IAAW,aAAA,CAAc,mBAAmB,OAAA,CAAQ,IAAA,IAAQ,QAAQ,WAAA,IAAe,iBAAA;AAAA,MACpG,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,cAAc,OAAA,CAAQ,YAAA;AAAA,MACtB,gBAAgB,OAAA,CAAQ,cAAA;AAAA,MACxB,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,QAAQ,aAAA,CAAc,cAAA;AAAA,MACtB,SAAA,EAAW,OAAA,CAAQ,SAAA,IAAa,aAAA,CAAc,oBAAoB,CAAC,CAAA;AAAA,MACnE,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,MAC3B,eAAe,OAAA,CAAQ;AAAA,KACxB,CAAA;AACD,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,eAAA,CAAgB,QAAQ,CAAA;AAEzC,IAAA,OAAO;AAAA,MACL,aAAA;AAAA,MACA,SAAA,EAAW,iBAAA;AAAA,MACX,gBAAgB,eAAA,CAAgB,cAAA;AAAA,MAChC,eAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,IAAA,GAAA,CAAI,WAAW,oCAAoC,CAAA;AACnD,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA,MAAMC,cAAAA,GAAgB,MAAM,uBAAA,CAAwB;AAAA,QAClD,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,IAAA,EAAM,QAAQ,IAAA,IAAQ,wBAAA;AAAA,QACtB,SAAA,EAAW,QAAQ,SAAA,IAAa,YAAA;AAAA,QAChC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,QACpB,YAAY,OAAA,CAAQ;AAAA,OACrB,CAAA;AAED,MAAA,MAAM,eAAA,GAAkB,MAAM,yBAAA,CAA0B;AAAA,QACtD,SAAS,OAAA,CAAQ,OAAA,IAAW,aAAA,CAAc,eAAA,IAAmB,QAAQ,IAAA,IAAQ,gBAAA;AAAA,QAC7E,aAAa,OAAA,CAAQ,WAAA;AAAA,QACrB,cAAc,OAAA,CAAQ,YAAA;AAAA,QACtB,gBAAgB,OAAA,CAAQ,cAAA;AAAA,QACxB,QAAQ,aAAA,CAAc,cAAA;AAAA,QACtB,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,OAAA,CAAQ;AAAA,OACrB,CAAA;AAED,MAAA,MAAM,YAAA,GAAe,MAAM,sBAAA,CAAuB;AAAA,QAChD,cAAcA,cAAAA,CAAc,YAAA;AAAA,QAC5B,gBAAgB,eAAA,CAAgB,cAAA;AAAA,QAChC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,OAAA,CAAQ;AAAA,OACrB,CAAA;AAED,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,YAAA,CAAa,QAAQ,CAAA;AACtC,MAAA,OAAO;AAAA,QACL,aAAA;AAAA,QACA,SAAA,EAAW,cAAA;AAAA,QACX,gBAAgB,YAAA,CAAa,cAAA;AAAA,QAC7B,aAAA,EAAAA,cAAAA;AAAA,QACA,eAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,KAAK,4HAAuH,CAAA;AACrI,MAAA,MAAM,eAAA,GAAkB,MAAM,yBAAA,CAA0B;AAAA,QACtD,SAAS,OAAA,CAAQ,OAAA,IAAW,aAAA,CAAc,eAAA,IAAmB,QAAQ,IAAA,IAAQ,gBAAA;AAAA,QAC7E,aAAa,OAAA,CAAQ,WAAA;AAAA,QACrB,cAAc,OAAA,CAAQ,YAAA;AAAA,QACtB,gBAAgB,OAAA,CAAQ,cAAA;AAAA,QACxB,QAAQ,aAAA,CAAc,cAAA;AAAA,QACtB,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,OAAA,CAAQ;AAAA,OACrB,CAAA;AACD,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,eAAA,CAAgB,QAAQ,CAAA;AAEzC,MAAA,OAAO;AAAA,QACL,aAAA;AAAA,QACA,SAAA,EAAW,iBAAA;AAAA,QACX,gBAAgB,eAAA,CAAgB,cAAA;AAAA,QAChC,eAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,GAAA,CAAI,WAAW,sDAAsD,CAAA;AACrE,EAAA,IAAI,CAAC,QAAQ,OAAA,EAAS;AACpB,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AAEA,EAAA,MAAM,aAAA,GAAgB,MAAM,uBAAA,CAAwB;AAAA,IAClD,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,IAAA,EAAM,QAAQ,IAAA,IAAQ,wBAAA;AAAA,IACtB,WAAW,OAAA,CAAQ,SAAA,IAAa,aAAA,CAAc,iBAAA,GAAoB,CAAC,CAAA,IAAK,YAAA;AAAA,IACxE,WAAW,OAAA,CAAQ,SAAA;AAAA,IACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,YAAY,OAAA,CAAQ;AAAA,GACrB,CAAA;AAGD,EAAA,MAAM,EAAE,kBAAA,EAAAC,mBAAAA,EAAmB,GAAI,MAAM,OAAO,sCAA+B,CAAA;AAC3E,EAAA,MAAM,cAAA,GAAiBA,mBAAAA,CAAmB,aAAA,CAAc,YAAA,EAAc;AAAA,IACpE;AAAA,GACD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,aAAA;AAAA,IACA,SAAA,EAAW,eAAA;AAAA,IACX,cAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF;AACF","file":"chunk-G7HLFMD2.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 } 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): 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 = 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 } 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}\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\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,\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 });\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 });\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,\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, llmConfig,\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 });\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 };\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';\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 });\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 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 });\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 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}\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) {\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 });\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 warnings.push('Hybrid learning mode requested but repoDir was not provided — falling back to concept-driven knowledge graph pipeline');\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 });\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\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\n const { emitCurriculumFeed } = await import('../feed/curriculumFeedEmitter');\n const curriculumFeed = emitCurriculumFeed(projectResult.projectGraph, {\n warnings,\n });\n\n return {\n domainProfile,\n graphType: 'project_graph',\n curriculumFeed,\n projectResult,\n warnings,\n };\n}\n"]}