@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.
- package/LICENSE +21 -0
- package/README.md +42 -11
- package/dist/{chunk-MSRKUZLY.mjs → chunk-E4GCCWJO.mjs} +32 -2
- package/dist/chunk-E4GCCWJO.mjs.map +1 -0
- package/dist/{chunk-MCHHEBH3.mjs → chunk-G7HLFMD2.mjs} +5 -5
- package/dist/{chunk-MCHHEBH3.mjs.map → chunk-G7HLFMD2.mjs.map} +1 -1
- package/dist/{chunk-LKSVTRQE.mjs → chunk-TWKIVUTQ.mjs} +33 -3
- package/dist/chunk-TWKIVUTQ.mjs.map +1 -0
- package/dist/{chunk-Y7MRFFDJ.mjs → chunk-TYXSJUQU.mjs} +100 -9
- package/dist/chunk-TYXSJUQU.mjs.map +1 -0
- package/dist/curriculumFeedEmitter-T7NUBLAM.mjs +4 -0
- package/dist/{curriculumFeedEmitter-FYAWMPE6.mjs.map → curriculumFeedEmitter-T7NUBLAM.mjs.map} +1 -1
- package/dist/{curriculumFeedSchema-C8ZP3XMi.d.ts → curriculumFeedSchema-DUFwFyr2.d.cts} +196 -0
- package/dist/{curriculumFeedSchema-C8ZP3XMi.d.cts → curriculumFeedSchema-DUFwFyr2.d.ts} +196 -0
- package/dist/feed/index.cjs +60 -0
- package/dist/feed/index.cjs.map +1 -1
- package/dist/feed/index.d.cts +1 -1
- package/dist/feed/index.d.ts +1 -1
- package/dist/feed/index.mjs +2 -2
- package/dist/graph/index.cjs +98 -6
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +1 -1
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/index.mjs +1 -1
- package/dist/{hybridGraphPipeline-NZAWAPt_.d.ts → hybridGraphPipeline-DXQDbBEj.d.ts} +14 -2
- package/dist/{hybridGraphPipeline-BhFyh3cm.d.cts → hybridGraphPipeline-dT-bio-3.d.cts} +14 -2
- package/dist/index.cjs +158 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +4 -4
- package/dist/pipeline/index.cjs +157 -6
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.d.cts +2 -2
- package/dist/pipeline/index.d.ts +2 -2
- package/dist/pipeline/index.mjs +4 -4
- package/dist/schemas/index.cjs +30 -0
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +1 -1
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.mjs +1 -1
- package/package.json +9 -10
- package/dist/chunk-LKSVTRQE.mjs.map +0 -1
- package/dist/chunk-MSRKUZLY.mjs.map +0 -1
- package/dist/chunk-Y7MRFFDJ.mjs.map +0 -1
- 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
|
-
//
|
|
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
|
-
// -
|
|
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
|
-
- **
|
|
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
|
|
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
|
-
→
|
|
727
|
-
→
|
|
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-
|
|
117
|
-
//# sourceMappingURL=chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
615
|
-
//# sourceMappingURL=chunk-
|
|
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":"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","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"]}
|