@thanh01.pmt/domain-kit 0.2.1 → 0.4.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/README.md +42 -11
- package/dist/{chunk-CRN6D4HG.mjs → chunk-HILSUZOF.mjs} +32 -8
- package/dist/chunk-HILSUZOF.mjs.map +1 -0
- package/dist/{chunk-23TQPTHG.mjs → chunk-LZQLLAYP.mjs} +5 -5
- package/dist/{chunk-23TQPTHG.mjs.map → chunk-LZQLLAYP.mjs.map} +1 -1
- package/dist/{chunk-HH4UX65C.mjs → chunk-PKUEOSZ3.mjs} +42 -4
- package/dist/chunk-PKUEOSZ3.mjs.map +1 -0
- package/dist/{chunk-HUDFN4IX.mjs → chunk-QJF4QCBJ.mjs} +99 -4
- package/dist/chunk-QJF4QCBJ.mjs.map +1 -0
- package/dist/{chunk-WHBAGJWN.mjs → chunk-VCPIWJ7R.mjs} +4 -4
- package/dist/chunk-VCPIWJ7R.mjs.map +1 -0
- package/dist/curriculumFeedEmitter-6IK6PFDH.mjs +4 -0
- package/dist/{curriculumFeedEmitter-E5DAJYUZ.mjs.map → curriculumFeedEmitter-6IK6PFDH.mjs.map} +1 -1
- package/dist/{curriculumFeedSchema-TEeQg2bY.d.ts → curriculumFeedSchema-B66H3gEV.d.cts} +148 -8
- package/dist/{curriculumFeedSchema-TEeQg2bY.d.cts → curriculumFeedSchema-B66H3gEV.d.ts} +148 -8
- package/dist/feed/index.cjs +136 -3
- 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 +30 -5
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +2 -2
- package/dist/graph/index.d.ts +2 -2
- package/dist/graph/index.mjs +1 -1
- package/dist/{hybridGraphPipeline-DVZYLCAQ.d.ts → hybridGraphPipeline-DXQDbBEj.d.ts} +14 -2
- package/dist/{hybridGraphPipeline-DmWRKYXf.d.cts → hybridGraphPipeline-dT-bio-3.d.cts} +14 -2
- package/dist/{hybridGraphSchema-BCgXicgA.d.ts → hybridGraphSchema-nrUeSwpU.d.cts} +15 -15
- package/dist/{hybridGraphSchema-BCgXicgA.d.cts → hybridGraphSchema-nrUeSwpU.d.ts} +15 -15
- package/dist/index.cjs +168 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +5 -5
- package/dist/pipeline/index.cjs +165 -8
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.d.cts +3 -3
- package/dist/pipeline/index.d.ts +3 -3
- package/dist/pipeline/index.mjs +4 -4
- package/dist/schemas/index.cjs +42 -4
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +2 -2
- package/dist/schemas/index.d.ts +2 -2
- package/dist/schemas/index.mjs +2 -2
- package/package.json +10 -9
- package/LICENSE +0 -21
- package/dist/chunk-CRN6D4HG.mjs.map +0 -1
- package/dist/chunk-HH4UX65C.mjs.map +0 -1
- package/dist/chunk-HUDFN4IX.mjs.map +0 -1
- package/dist/chunk-WHBAGJWN.mjs.map +0 -1
- package/dist/curriculumFeedEmitter-E5DAJYUZ.mjs +0 -4
package/dist/graph/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { L as LlmClientConfig } from '../llmClient-ysPhLjcH.cjs';
|
|
2
2
|
import { d as Feature, c as Step } from '../projectGraphSchema-DnD7orZV.cjs';
|
|
3
3
|
import { K as Keyword } from '../keywordExtractor-BxlGRMHC.cjs';
|
|
4
|
-
export { H as Hallucination,
|
|
4
|
+
export { H as Hallucination, j as HybridGraphPipelineOptions, k as HybridGraphPipelineResult, K as KnowledgeGraphPipelineOptions, a as KnowledgeGraphPipelineResult, f as KnowledgeGraphVerificationReport, V as VerifyOptions, i as auditPhasePlan, e as auditSyllabusCoverage, c as breakPrerequisiteCycles, d as detectPrerequisiteCycles, h as generateHybridGraph, g as generateKnowledgeGraph, b as verifyKnowledgeGraph, v as verifyProjectGraph } from '../hybridGraphPipeline-dT-bio-3.cjs';
|
|
5
5
|
export { C as ConceptMapping, E as EscalateOptions, e as escalateAndMapConcepts } from '../conceptEscalator-ltRLtPhf.cjs';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import '../cpp-CZUPqJt9.cjs';
|
|
8
|
-
import '../hybridGraphSchema-
|
|
8
|
+
import '../hybridGraphSchema-nrUeSwpU.cjs';
|
|
9
9
|
import '../syllabusParser-MSX1fEzW.cjs';
|
|
10
10
|
|
|
11
11
|
/**
|
package/dist/graph/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { L as LlmClientConfig } from '../llmClient-ysPhLjcH.js';
|
|
2
2
|
import { d as Feature, c as Step } from '../projectGraphSchema-DnD7orZV.js';
|
|
3
3
|
import { K as Keyword } from '../keywordExtractor-DU5XRN8-.js';
|
|
4
|
-
export { H as Hallucination,
|
|
4
|
+
export { H as Hallucination, j as HybridGraphPipelineOptions, k as HybridGraphPipelineResult, K as KnowledgeGraphPipelineOptions, a as KnowledgeGraphPipelineResult, f as KnowledgeGraphVerificationReport, V as VerifyOptions, i as auditPhasePlan, e as auditSyllabusCoverage, c as breakPrerequisiteCycles, d as detectPrerequisiteCycles, h as generateHybridGraph, g as generateKnowledgeGraph, b as verifyKnowledgeGraph, v as verifyProjectGraph } from '../hybridGraphPipeline-DXQDbBEj.js';
|
|
5
5
|
export { C as ConceptMapping, E as EscalateOptions, e as escalateAndMapConcepts } from '../conceptEscalator-YfMKIKCZ.js';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import '../cpp-CZUPqJt9.js';
|
|
8
|
-
import '../hybridGraphSchema-
|
|
8
|
+
import '../hybridGraphSchema-nrUeSwpU.js';
|
|
9
9
|
import '../syllabusParser-MSX1fEzW.js';
|
|
10
10
|
|
|
11
11
|
/**
|
package/dist/graph/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../chunk-ZKLT27T4.mjs';
|
|
2
|
-
export { CIO_CODE_RE, CONCEPT_CODE_RE, LEARNER_CLAUSE, SIO_CODE_RE, ULO_CODE_RE, assignConceptCodes, auditDepthLayers, auditSyllabusCoverage, breakPrerequisiteCycles, cioActionSlug, cioCode, conceptCodeFromName, detectPrerequisiteCycles, escalateAndMapConcepts, extractFeatureSteps, extractFeatureStepsBatched, extractProjectOverview, extractScaffold, generateHybridGraph, generateKnowledgeGraph, sioCode, standardStatement, techTagFor, uloCode, verifyKnowledgeGraph, verifyProjectGraph } from '../chunk-
|
|
2
|
+
export { CIO_CODE_RE, CONCEPT_CODE_RE, LEARNER_CLAUSE, SIO_CODE_RE, ULO_CODE_RE, assignConceptCodes, auditDepthLayers, auditPhasePlan, auditSyllabusCoverage, breakPrerequisiteCycles, cioActionSlug, cioCode, conceptCodeFromName, detectPrerequisiteCycles, escalateAndMapConcepts, extractFeatureSteps, extractFeatureStepsBatched, extractProjectOverview, extractScaffold, generateHybridGraph, generateKnowledgeGraph, sioCode, standardStatement, techTagFor, uloCode, verifyKnowledgeGraph, verifyProjectGraph } from '../chunk-HILSUZOF.mjs';
|
|
3
3
|
import '../chunk-T4Y2DE2W.mjs';
|
|
4
4
|
//# sourceMappingURL=index.mjs.map
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { u as ProjectGraph } from './projectGraphSchema-DnD7orZV.js';
|
|
2
2
|
import { L as LlmClientConfig } from './llmClient-ysPhLjcH.js';
|
|
3
|
-
import { g as KnowledgeGraph, b as Concept, j as HybridGraph } from './hybridGraphSchema-
|
|
3
|
+
import { g as KnowledgeGraph, b as Concept, j as HybridGraph, l as DevelopmentPhase } from './hybridGraphSchema-nrUeSwpU.js';
|
|
4
4
|
import { P as ParsedSyllabus } from './syllabusParser-MSX1fEzW.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -155,5 +155,17 @@ interface HybridGraphPipelineResult {
|
|
|
155
155
|
warnings: string[];
|
|
156
156
|
}
|
|
157
157
|
declare function generateHybridGraph(options: HybridGraphPipelineOptions): Promise<HybridGraphPipelineResult>;
|
|
158
|
+
declare function auditPhasePlan(plan: Array<Record<string, unknown>>, features: Array<{
|
|
159
|
+
id: string;
|
|
160
|
+
}>, concepts: Array<{
|
|
161
|
+
id: string;
|
|
162
|
+
prerequisites?: string[];
|
|
163
|
+
}>, links: Array<{
|
|
164
|
+
feature_id: string;
|
|
165
|
+
concept_id: string;
|
|
166
|
+
}>, warnings: string[], log: (step: string, msg: string) => void): {
|
|
167
|
+
phases: DevelopmentPhase[];
|
|
168
|
+
errors: string[];
|
|
169
|
+
};
|
|
158
170
|
|
|
159
|
-
export { type Hallucination as H, type KnowledgeGraphPipelineOptions as K, type VerifyOptions as V, type KnowledgeGraphPipelineResult as a, verifyKnowledgeGraph as b, breakPrerequisiteCycles as c, detectPrerequisiteCycles as d, auditSyllabusCoverage as e, type KnowledgeGraphVerificationReport as f, generateKnowledgeGraph as g, generateHybridGraph as h, type HybridGraphPipelineOptions as
|
|
171
|
+
export { type Hallucination as H, type KnowledgeGraphPipelineOptions as K, type VerifyOptions as V, type KnowledgeGraphPipelineResult as a, verifyKnowledgeGraph as b, breakPrerequisiteCycles as c, detectPrerequisiteCycles as d, auditSyllabusCoverage as e, type KnowledgeGraphVerificationReport as f, generateKnowledgeGraph as g, generateHybridGraph as h, auditPhasePlan as i, type HybridGraphPipelineOptions as j, type HybridGraphPipelineResult as k, verifyProjectGraph as v };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { u as ProjectGraph } from './projectGraphSchema-DnD7orZV.cjs';
|
|
2
2
|
import { L as LlmClientConfig } from './llmClient-ysPhLjcH.cjs';
|
|
3
|
-
import { g as KnowledgeGraph, b as Concept, j as HybridGraph } from './hybridGraphSchema-
|
|
3
|
+
import { g as KnowledgeGraph, b as Concept, j as HybridGraph, l as DevelopmentPhase } from './hybridGraphSchema-nrUeSwpU.cjs';
|
|
4
4
|
import { P as ParsedSyllabus } from './syllabusParser-MSX1fEzW.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -155,5 +155,17 @@ interface HybridGraphPipelineResult {
|
|
|
155
155
|
warnings: string[];
|
|
156
156
|
}
|
|
157
157
|
declare function generateHybridGraph(options: HybridGraphPipelineOptions): Promise<HybridGraphPipelineResult>;
|
|
158
|
+
declare function auditPhasePlan(plan: Array<Record<string, unknown>>, features: Array<{
|
|
159
|
+
id: string;
|
|
160
|
+
}>, concepts: Array<{
|
|
161
|
+
id: string;
|
|
162
|
+
prerequisites?: string[];
|
|
163
|
+
}>, links: Array<{
|
|
164
|
+
feature_id: string;
|
|
165
|
+
concept_id: string;
|
|
166
|
+
}>, warnings: string[], log: (step: string, msg: string) => void): {
|
|
167
|
+
phases: DevelopmentPhase[];
|
|
168
|
+
errors: string[];
|
|
169
|
+
};
|
|
158
170
|
|
|
159
|
-
export { type Hallucination as H, type KnowledgeGraphPipelineOptions as K, type VerifyOptions as V, type KnowledgeGraphPipelineResult as a, verifyKnowledgeGraph as b, breakPrerequisiteCycles as c, detectPrerequisiteCycles as d, auditSyllabusCoverage as e, type KnowledgeGraphVerificationReport as f, generateKnowledgeGraph as g, generateHybridGraph as h, type HybridGraphPipelineOptions as
|
|
171
|
+
export { type Hallucination as H, type KnowledgeGraphPipelineOptions as K, type VerifyOptions as V, type KnowledgeGraphPipelineResult as a, verifyKnowledgeGraph as b, breakPrerequisiteCycles as c, detectPrerequisiteCycles as d, auditSyllabusCoverage as e, type KnowledgeGraphVerificationReport as f, generateKnowledgeGraph as g, generateHybridGraph as h, auditPhasePlan as i, type HybridGraphPipelineOptions as j, type HybridGraphPipelineResult as k, verifyProjectGraph as v };
|
|
@@ -563,15 +563,15 @@ declare const ProjectConceptLinkSchema: z.ZodObject<{
|
|
|
563
563
|
}>;
|
|
564
564
|
declare const ConceptIntroductionSchema: z.ZodObject<{
|
|
565
565
|
concept_id: z.ZodString;
|
|
566
|
-
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced"]>>;
|
|
566
|
+
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced", "preview"]>>;
|
|
567
567
|
note: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
568
568
|
}, "strip", z.ZodTypeAny, {
|
|
569
569
|
concept_id: string;
|
|
570
|
-
aspect: "new" | "advanced";
|
|
570
|
+
aspect: "new" | "advanced" | "preview";
|
|
571
571
|
note: string;
|
|
572
572
|
}, {
|
|
573
573
|
concept_id: string;
|
|
574
|
-
aspect?: "new" | "advanced" | undefined;
|
|
574
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
575
575
|
note?: string | undefined;
|
|
576
576
|
}>;
|
|
577
577
|
declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
@@ -582,15 +582,15 @@ declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
|
582
582
|
feature_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
583
583
|
introduces: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
584
584
|
concept_id: z.ZodString;
|
|
585
|
-
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced"]>>;
|
|
585
|
+
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced", "preview"]>>;
|
|
586
586
|
note: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
587
587
|
}, "strip", z.ZodTypeAny, {
|
|
588
588
|
concept_id: string;
|
|
589
|
-
aspect: "new" | "advanced";
|
|
589
|
+
aspect: "new" | "advanced" | "preview";
|
|
590
590
|
note: string;
|
|
591
591
|
}, {
|
|
592
592
|
concept_id: string;
|
|
593
|
-
aspect?: "new" | "advanced" | undefined;
|
|
593
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
594
594
|
note?: string | undefined;
|
|
595
595
|
}>, "many">>;
|
|
596
596
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -601,7 +601,7 @@ declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
|
601
601
|
product_completion: string;
|
|
602
602
|
introduces: {
|
|
603
603
|
concept_id: string;
|
|
604
|
-
aspect: "new" | "advanced";
|
|
604
|
+
aspect: "new" | "advanced" | "preview";
|
|
605
605
|
note: string;
|
|
606
606
|
}[];
|
|
607
607
|
}, {
|
|
@@ -612,7 +612,7 @@ declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
|
612
612
|
feature_ids?: string[] | undefined;
|
|
613
613
|
introduces?: {
|
|
614
614
|
concept_id: string;
|
|
615
|
-
aspect?: "new" | "advanced" | undefined;
|
|
615
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
616
616
|
note?: string | undefined;
|
|
617
617
|
}[] | undefined;
|
|
618
618
|
}>;
|
|
@@ -2211,15 +2211,15 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2211
2211
|
feature_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
2212
2212
|
introduces: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
2213
2213
|
concept_id: z.ZodString;
|
|
2214
|
-
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced"]>>;
|
|
2214
|
+
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced", "preview"]>>;
|
|
2215
2215
|
note: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
2216
2216
|
}, "strip", z.ZodTypeAny, {
|
|
2217
2217
|
concept_id: string;
|
|
2218
|
-
aspect: "new" | "advanced";
|
|
2218
|
+
aspect: "new" | "advanced" | "preview";
|
|
2219
2219
|
note: string;
|
|
2220
2220
|
}, {
|
|
2221
2221
|
concept_id: string;
|
|
2222
|
-
aspect?: "new" | "advanced" | undefined;
|
|
2222
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
2223
2223
|
note?: string | undefined;
|
|
2224
2224
|
}>, "many">>;
|
|
2225
2225
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -2230,7 +2230,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2230
2230
|
product_completion: string;
|
|
2231
2231
|
introduces: {
|
|
2232
2232
|
concept_id: string;
|
|
2233
|
-
aspect: "new" | "advanced";
|
|
2233
|
+
aspect: "new" | "advanced" | "preview";
|
|
2234
2234
|
note: string;
|
|
2235
2235
|
}[];
|
|
2236
2236
|
}, {
|
|
@@ -2241,7 +2241,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2241
2241
|
feature_ids?: string[] | undefined;
|
|
2242
2242
|
introduces?: {
|
|
2243
2243
|
concept_id: string;
|
|
2244
|
-
aspect?: "new" | "advanced" | undefined;
|
|
2244
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
2245
2245
|
note?: string | undefined;
|
|
2246
2246
|
}[] | undefined;
|
|
2247
2247
|
}>, "many">>>;
|
|
@@ -2533,7 +2533,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2533
2533
|
product_completion: string;
|
|
2534
2534
|
introduces: {
|
|
2535
2535
|
concept_id: string;
|
|
2536
|
-
aspect: "new" | "advanced";
|
|
2536
|
+
aspect: "new" | "advanced" | "preview";
|
|
2537
2537
|
note: string;
|
|
2538
2538
|
}[];
|
|
2539
2539
|
}[];
|
|
@@ -2824,7 +2824,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2824
2824
|
feature_ids?: string[] | undefined;
|
|
2825
2825
|
introduces?: {
|
|
2826
2826
|
concept_id: string;
|
|
2827
|
-
aspect?: "new" | "advanced" | undefined;
|
|
2827
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
2828
2828
|
note?: string | undefined;
|
|
2829
2829
|
}[] | undefined;
|
|
2830
2830
|
}[] | undefined;
|
|
@@ -563,15 +563,15 @@ declare const ProjectConceptLinkSchema: z.ZodObject<{
|
|
|
563
563
|
}>;
|
|
564
564
|
declare const ConceptIntroductionSchema: z.ZodObject<{
|
|
565
565
|
concept_id: z.ZodString;
|
|
566
|
-
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced"]>>;
|
|
566
|
+
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced", "preview"]>>;
|
|
567
567
|
note: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
568
568
|
}, "strip", z.ZodTypeAny, {
|
|
569
569
|
concept_id: string;
|
|
570
|
-
aspect: "new" | "advanced";
|
|
570
|
+
aspect: "new" | "advanced" | "preview";
|
|
571
571
|
note: string;
|
|
572
572
|
}, {
|
|
573
573
|
concept_id: string;
|
|
574
|
-
aspect?: "new" | "advanced" | undefined;
|
|
574
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
575
575
|
note?: string | undefined;
|
|
576
576
|
}>;
|
|
577
577
|
declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
@@ -582,15 +582,15 @@ declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
|
582
582
|
feature_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
583
583
|
introduces: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
584
584
|
concept_id: z.ZodString;
|
|
585
|
-
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced"]>>;
|
|
585
|
+
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced", "preview"]>>;
|
|
586
586
|
note: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
587
587
|
}, "strip", z.ZodTypeAny, {
|
|
588
588
|
concept_id: string;
|
|
589
|
-
aspect: "new" | "advanced";
|
|
589
|
+
aspect: "new" | "advanced" | "preview";
|
|
590
590
|
note: string;
|
|
591
591
|
}, {
|
|
592
592
|
concept_id: string;
|
|
593
|
-
aspect?: "new" | "advanced" | undefined;
|
|
593
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
594
594
|
note?: string | undefined;
|
|
595
595
|
}>, "many">>;
|
|
596
596
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -601,7 +601,7 @@ declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
|
601
601
|
product_completion: string;
|
|
602
602
|
introduces: {
|
|
603
603
|
concept_id: string;
|
|
604
|
-
aspect: "new" | "advanced";
|
|
604
|
+
aspect: "new" | "advanced" | "preview";
|
|
605
605
|
note: string;
|
|
606
606
|
}[];
|
|
607
607
|
}, {
|
|
@@ -612,7 +612,7 @@ declare const DevelopmentPhaseSchema: z.ZodObject<{
|
|
|
612
612
|
feature_ids?: string[] | undefined;
|
|
613
613
|
introduces?: {
|
|
614
614
|
concept_id: string;
|
|
615
|
-
aspect?: "new" | "advanced" | undefined;
|
|
615
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
616
616
|
note?: string | undefined;
|
|
617
617
|
}[] | undefined;
|
|
618
618
|
}>;
|
|
@@ -2211,15 +2211,15 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2211
2211
|
feature_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
2212
2212
|
introduces: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
2213
2213
|
concept_id: z.ZodString;
|
|
2214
|
-
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced"]>>;
|
|
2214
|
+
aspect: z.ZodDefault<z.ZodEnum<["new", "advanced", "preview"]>>;
|
|
2215
2215
|
note: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
2216
2216
|
}, "strip", z.ZodTypeAny, {
|
|
2217
2217
|
concept_id: string;
|
|
2218
|
-
aspect: "new" | "advanced";
|
|
2218
|
+
aspect: "new" | "advanced" | "preview";
|
|
2219
2219
|
note: string;
|
|
2220
2220
|
}, {
|
|
2221
2221
|
concept_id: string;
|
|
2222
|
-
aspect?: "new" | "advanced" | undefined;
|
|
2222
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
2223
2223
|
note?: string | undefined;
|
|
2224
2224
|
}>, "many">>;
|
|
2225
2225
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -2230,7 +2230,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2230
2230
|
product_completion: string;
|
|
2231
2231
|
introduces: {
|
|
2232
2232
|
concept_id: string;
|
|
2233
|
-
aspect: "new" | "advanced";
|
|
2233
|
+
aspect: "new" | "advanced" | "preview";
|
|
2234
2234
|
note: string;
|
|
2235
2235
|
}[];
|
|
2236
2236
|
}, {
|
|
@@ -2241,7 +2241,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2241
2241
|
feature_ids?: string[] | undefined;
|
|
2242
2242
|
introduces?: {
|
|
2243
2243
|
concept_id: string;
|
|
2244
|
-
aspect?: "new" | "advanced" | undefined;
|
|
2244
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
2245
2245
|
note?: string | undefined;
|
|
2246
2246
|
}[] | undefined;
|
|
2247
2247
|
}>, "many">>>;
|
|
@@ -2533,7 +2533,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2533
2533
|
product_completion: string;
|
|
2534
2534
|
introduces: {
|
|
2535
2535
|
concept_id: string;
|
|
2536
|
-
aspect: "new" | "advanced";
|
|
2536
|
+
aspect: "new" | "advanced" | "preview";
|
|
2537
2537
|
note: string;
|
|
2538
2538
|
}[];
|
|
2539
2539
|
}[];
|
|
@@ -2824,7 +2824,7 @@ declare const HybridGraphSchema: z.ZodObject<{
|
|
|
2824
2824
|
feature_ids?: string[] | undefined;
|
|
2825
2825
|
introduces?: {
|
|
2826
2826
|
concept_id: string;
|
|
2827
|
-
aspect?: "new" | "advanced" | undefined;
|
|
2827
|
+
aspect?: "new" | "advanced" | "preview" | undefined;
|
|
2828
2828
|
note?: string | undefined;
|
|
2829
2829
|
}[] | undefined;
|
|
2830
2830
|
}[] | undefined;
|
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,22 @@ function validateCurriculumFeed(feed) {
|
|
|
39
39
|
}
|
|
40
40
|
const phaseIds = parsed.phases.map((p) => p.id);
|
|
41
41
|
if (new Set(phaseIds).size !== phaseIds.length) throw new Error("curriculum feed contains duplicate phase ids");
|
|
42
|
+
if (parsed.phases.length > 0) {
|
|
43
|
+
const phaseIndexOf = /* @__PURE__ */ new Map();
|
|
44
|
+
parsed.phases.forEach((p, i) => {
|
|
45
|
+
for (const id of p.node_ids) phaseIndexOf.set(id, i);
|
|
46
|
+
});
|
|
47
|
+
for (const e of parsed.dependency_edges) {
|
|
48
|
+
const fromIdx = phaseIndexOf.get(e.from);
|
|
49
|
+
const toIdx = phaseIndexOf.get(e.to);
|
|
50
|
+
if (fromIdx === void 0 || toIdx === void 0) continue;
|
|
51
|
+
if (fromIdx > toIdx) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
"curriculum feed teaching-order violation: prerequisite " + e.from + " (phase " + (fromIdx + 1) + ") is scheduled AFTER its consumer " + e.to + " (phase " + (toIdx + 1) + ")"
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
42
58
|
return parsed;
|
|
43
59
|
}
|
|
44
60
|
exports.FeedKeywordsSchema = void 0; exports.FeedScaffoldCandidateSchema = void 0; exports.FeedNodeSchema = void 0; exports.FeedEdgeSchema = void 0; exports.FeedGroupingSchema = void 0; exports.FeedPhaseSchema = void 0; exports.CurriculumFeedSchema = void 0;
|
|
@@ -72,11 +88,33 @@ var init_curriculumFeedSchema = __esm({
|
|
|
72
88
|
references: zod.z.array(zod.z.object({ file: zod.z.string().min(1), evidence: zod.z.string().default("") })).default([]),
|
|
73
89
|
feature_id: zod.z.string().nullable().default(null),
|
|
74
90
|
concept_ref: zod.z.string().nullable().default(null),
|
|
91
|
+
// P52/T2.1: outcome.user_visible projected from the ProjectGraph step — the
|
|
92
|
+
// tangible checkpoint the session-cutting planner aims for (empty when the
|
|
93
|
+
// step declares no user-visible result). Concepts carry '' by default.
|
|
94
|
+
user_visible_deliverable: zod.z.string().default(""),
|
|
95
|
+
// P52/T3.1 — depth-reconcile inputs (optional/defaulted so old feeds
|
|
96
|
+
// validate unchanged):
|
|
97
|
+
// • depth_variants: minutes to teach this node at each depth level.
|
|
98
|
+
// ULO (know-it-exists) ≤ CIO (mechanism) ≤ SIO (implementation). All 3
|
|
99
|
+
// required so a downgrade never turns an anchor teach into a zero.
|
|
100
|
+
// • depth_scaffold_candidates: parallel to scaffold_candidates but
|
|
101
|
+
// acts on DEPTH (e.g. SIO→CIO) instead of lesson time.
|
|
102
|
+
// • is_core: concept is a Master-Tree core concept — reconciler must
|
|
103
|
+
// never downgrade it; escalate instead.
|
|
104
|
+
depth_variants: zod.z.object({ ulo: zod.z.number().int().nonnegative(), cio: zod.z.number().int().nonnegative(), sio: zod.z.number().int().nonnegative() }).optional(),
|
|
105
|
+
depth_scaffold_candidates: zod.z.array(zod.z.object({
|
|
106
|
+
from_depth: zod.z.enum(["ulo", "cio", "sio"]),
|
|
107
|
+
to_depth: zod.z.enum(["ulo", "cio", "sio"]),
|
|
108
|
+
minutes_saved: zod.z.number().int().nonnegative(),
|
|
109
|
+
reason: zod.z.string().default("")
|
|
110
|
+
})).optional(),
|
|
111
|
+
is_core: zod.z.boolean().default(false),
|
|
75
112
|
// Progressive-completion bookkeeping (feed v2, additive):
|
|
76
113
|
// phase_id = development phase that introduces/uses this node;
|
|
77
|
-
// introduce_aspect = how the phase teaches a concept node (first intro
|
|
114
|
+
// introduce_aspect = how the phase teaches a concept node (first intro, advanced
|
|
115
|
+
// revisit, or preview — a light ULO awareness pass that is NOT the introduction).
|
|
78
116
|
phase_id: zod.z.string().default(""),
|
|
79
|
-
introduce_aspect: zod.z.enum(["new", "advanced"]).nullable().default(null)
|
|
117
|
+
introduce_aspect: zod.z.enum(["new", "advanced", "preview"]).nullable().default(null)
|
|
80
118
|
});
|
|
81
119
|
exports.FeedEdgeSchema = zod.z.object({
|
|
82
120
|
from: zod.z.string().min(1),
|
|
@@ -123,6 +161,9 @@ function stepMinutes(step) {
|
|
|
123
161
|
const effort = step.effort ?? {};
|
|
124
162
|
return Math.max(0, Math.round(num(effort.estimated_minutes, num(step.estimated_minutes, 45))));
|
|
125
163
|
}
|
|
164
|
+
function pushWarning(opts, message) {
|
|
165
|
+
(opts.warnings ?? (opts.warnings = [])).push(message);
|
|
166
|
+
}
|
|
126
167
|
function newKeywordsInOrder(nodes) {
|
|
127
168
|
const seen = /* @__PURE__ */ new Set();
|
|
128
169
|
for (const n of nodes) {
|
|
@@ -152,6 +193,10 @@ function feedNodeFromStep(step, featureId) {
|
|
|
152
193
|
references: arr(step.files).map((f) => ({ file: str(f), evidence: "step file" })).filter((f) => f.file),
|
|
153
194
|
feature_id: featureId,
|
|
154
195
|
concept_ref: null,
|
|
196
|
+
// P52/T2.1: carry the step's tangible outcome so the planner can cut
|
|
197
|
+
// sessions at user-visible checkpoints instead of raw minute counts.
|
|
198
|
+
user_visible_deliverable: str(step.outcome?.user_visible),
|
|
199
|
+
is_core: false,
|
|
155
200
|
phase_id: "",
|
|
156
201
|
introduce_aspect: null
|
|
157
202
|
};
|
|
@@ -170,6 +215,20 @@ function deriveConceptDepthHint(concept) {
|
|
|
170
215
|
if (str(concept.cio) || prereqs.length >= 1) return "cio";
|
|
171
216
|
return "ulo";
|
|
172
217
|
}
|
|
218
|
+
function deriveDepthInputs(minutes, depth) {
|
|
219
|
+
const ulo = Math.max(5, Math.round(minutes * 0.35));
|
|
220
|
+
const cio = Math.max(ulo + 5, Math.round(minutes * 0.65));
|
|
221
|
+
const sio = Math.max(cio + 5, minutes);
|
|
222
|
+
const variants = { ulo, cio, sio };
|
|
223
|
+
const candidates = [];
|
|
224
|
+
if (depth === "sio") {
|
|
225
|
+
candidates.push({ from_depth: "sio", to_depth: "cio", minutes_saved: sio - cio, reason: "SIO implementation practice deferred \u2014 CIO mechanism suffices for downstream consumers" });
|
|
226
|
+
}
|
|
227
|
+
if (depth === "cio" || depth === "sio") {
|
|
228
|
+
candidates.push({ from_depth: depth, to_depth: "ulo", minutes_saved: (depth === "sio" ? sio : cio) - ulo, reason: "Mechanism deferred \u2014 ULO awareness suffices (know-it-exists); never below the ULO floor" });
|
|
229
|
+
}
|
|
230
|
+
return { depth_variants: variants, depth_scaffold_candidates: candidates };
|
|
231
|
+
}
|
|
173
232
|
function feedNodeFromConcept(concept) {
|
|
174
233
|
const id = str(concept.id);
|
|
175
234
|
const pts = arr(concept.problem_types).map((p) => str(p.bloom_level, "Understand")).filter((b) => b in BLOOM_RANK).sort((a, b) => BLOOM_RANK[a] - BLOOM_RANK[b]);
|
|
@@ -199,6 +258,10 @@ function feedNodeFromConcept(concept) {
|
|
|
199
258
|
references,
|
|
200
259
|
feature_id: null,
|
|
201
260
|
concept_ref: id,
|
|
261
|
+
user_visible_deliverable: "",
|
|
262
|
+
// concepts are taught, not shipped — checkpoints live on product steps
|
|
263
|
+
...deriveDepthInputs(Math.max(0, Math.round(num(concept.estimated_minutes, 15))), deriveConceptDepthHint(concept)),
|
|
264
|
+
is_core: false,
|
|
202
265
|
phase_id: "",
|
|
203
266
|
introduce_aspect: null
|
|
204
267
|
};
|
|
@@ -259,6 +322,7 @@ function emitFromHybrid(hybrid, opts) {
|
|
|
259
322
|
}
|
|
260
323
|
const emitCtx = [];
|
|
261
324
|
const emittedConcepts = /* @__PURE__ */ new Set();
|
|
325
|
+
const previewsEmitted = /* @__PURE__ */ new Set();
|
|
262
326
|
const linkList = arr(hybrid.links);
|
|
263
327
|
for (const rp of rawPhases) {
|
|
264
328
|
const pid = str(rp.id);
|
|
@@ -267,7 +331,8 @@ function emitFromHybrid(hybrid, opts) {
|
|
|
267
331
|
const intros = arr(rp.introduces);
|
|
268
332
|
const news = intros.filter((i) => str(i.aspect, "new") === "new");
|
|
269
333
|
const advanced = intros.filter((i) => str(i.aspect) === "advanced");
|
|
270
|
-
|
|
334
|
+
const previews = intros.filter((i) => str(i.aspect) === "preview");
|
|
335
|
+
for (const intro of [...news, ...advanced, ...previews]) {
|
|
271
336
|
const cid = str(intro.concept_id);
|
|
272
337
|
const c = conceptById.get(cid);
|
|
273
338
|
if (!c) {
|
|
@@ -276,6 +341,39 @@ function emitFromHybrid(hybrid, opts) {
|
|
|
276
341
|
if (str(intro.aspect, "new") === "advanced" && !emittedConcepts.has(cid)) {
|
|
277
342
|
throw new Error("Phase " + pid + " advanced-revisits concept " + cid + " that was never emitted - fail-closed");
|
|
278
343
|
}
|
|
344
|
+
if (str(intro.aspect, "new") === "preview") {
|
|
345
|
+
if (emittedConcepts.has(cid)) {
|
|
346
|
+
throw new Error("Phase " + pid + " previews concept " + cid + " that was already introduced - preview must precede the anchor teach - fail-closed");
|
|
347
|
+
}
|
|
348
|
+
if (previewsEmitted.has(cid)) {
|
|
349
|
+
throw new Error("Phase " + pid + " duplicate preview of concept " + cid + " - fail-closed");
|
|
350
|
+
}
|
|
351
|
+
const pidIdx = rawPhases.findIndex((rp2) => str(rp2.id) === pid);
|
|
352
|
+
const anchorIdx = rawPhases.findIndex((rp2) => arr(rp2.introduces).some((i2) => str(i2.concept_id) === cid && str(i2.aspect, "new") !== "preview"));
|
|
353
|
+
if (anchorIdx < 0) {
|
|
354
|
+
throw new Error("Phase " + pid + " previews concept " + cid + " that is never fully introduced in any phase - fail-closed");
|
|
355
|
+
}
|
|
356
|
+
if (pidIdx >= anchorIdx) {
|
|
357
|
+
throw new Error("Phase " + pid + " previews concept " + cid + " whose anchor introduction is not in a LATER phase - fail-closed");
|
|
358
|
+
}
|
|
359
|
+
previewsEmitted.add(cid);
|
|
360
|
+
const prevNode = feedNodeFromConcept(c);
|
|
361
|
+
prevNode.id = cid + "__PREV" + pad22(order);
|
|
362
|
+
prevNode.name = str(c.name, cid) + " (preview)";
|
|
363
|
+
prevNode.phase_id = pid;
|
|
364
|
+
prevNode.introduce_aspect = "preview";
|
|
365
|
+
prevNode.estimated_minutes = Math.max(5, Math.round(prevNode.estimated_minutes * 0.25));
|
|
366
|
+
prevNode.depth_hint = "ulo";
|
|
367
|
+
prevNode.bloom_hint = "Understand";
|
|
368
|
+
prevNode.concept_codes = [str(c.code) || cid];
|
|
369
|
+
prevNode.keywords = { all: strs(c.keywords), new: [], prerequisite: [] };
|
|
370
|
+
prevNode.scaffolding = { scaffold_candidates: [], core_value_minutes: 0 };
|
|
371
|
+
prevNode.depth_variants = { ulo: prevNode.estimated_minutes, cio: prevNode.estimated_minutes, sio: prevNode.estimated_minutes };
|
|
372
|
+
prevNode.depth_scaffold_candidates = [];
|
|
373
|
+
nodes.push(prevNode);
|
|
374
|
+
conceptOrder.push(prevNode.id);
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
279
377
|
if (!emittedConcepts.has(cid)) {
|
|
280
378
|
const node = feedNodeFromConcept(c);
|
|
281
379
|
node.phase_id = pid;
|
|
@@ -296,6 +394,7 @@ function emitFromHybrid(hybrid, opts) {
|
|
|
296
394
|
node.name = str(c.name, cid) + " (advanced)";
|
|
297
395
|
node.phase_id = pid;
|
|
298
396
|
node.introduce_aspect = "advanced";
|
|
397
|
+
node.depth_scaffold_candidates = [{ from_depth: "sio", to_depth: "cio", minutes_saved: Math.round(node.estimated_minutes * 0.3), reason: "advanced revisit may drop to CIO recap without breaking first-teach chain" }];
|
|
299
398
|
node.estimated_minutes = Math.max(15, Math.round(node.estimated_minutes * 0.5));
|
|
300
399
|
node.concept_codes = [str(c.code) || cid];
|
|
301
400
|
edges.push({ from: cid, to: revisitId, kind: "knowledge", reason: "advanced revisit of " + cid + " at phase " + pid });
|
|
@@ -331,6 +430,17 @@ function emitFromHybrid(hybrid, opts) {
|
|
|
331
430
|
}
|
|
332
431
|
phaseNodeIds.push(ids);
|
|
333
432
|
}
|
|
433
|
+
const placed = new Set(phaseNodeIds.flat());
|
|
434
|
+
const orderedNodes = [];
|
|
435
|
+
for (const ids of phaseNodeIds) {
|
|
436
|
+
for (const id of ids) {
|
|
437
|
+
const n = nodes.find((x) => x.id === id);
|
|
438
|
+
if (n) orderedNodes.push(n);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
for (const n of nodes) if (!placed.has(n.id)) orderedNodes.push(n);
|
|
442
|
+
nodes.length = 0;
|
|
443
|
+
nodes.push(...orderedNodes);
|
|
334
444
|
const edgeSeen = new Set(edges.map((e) => e.from + ">" + e.to));
|
|
335
445
|
const pushEdge = (from, to, reason) => {
|
|
336
446
|
const key = from + ">" + to;
|
|
@@ -345,6 +455,14 @@ function emitFromHybrid(hybrid, opts) {
|
|
|
345
455
|
const firstStep = (stepIdsByFeature.get(fid) || [])[0];
|
|
346
456
|
if (!firstStep) continue;
|
|
347
457
|
const depth = str(l.depth, "cio");
|
|
458
|
+
const anchorNode = nodes.find((n2) => n2.kind === "concept" && n2.concept_ref === cid && n2.introduce_aspect === "new");
|
|
459
|
+
const stepNode = nodes.find((n2) => n2.id === firstStep);
|
|
460
|
+
const anchorPhaseIdx = anchorNode ? emitCtx.findIndex((c2) => c2.id === anchorNode.phase_id) : -1;
|
|
461
|
+
const stepPhaseIdx = stepNode ? emitCtx.findIndex((c2) => c2.id === stepNode.phase_id) : -1;
|
|
462
|
+
if (emitCtx.length > 0 && anchorPhaseIdx > stepPhaseIdx) {
|
|
463
|
+
pushWarning(opts, "hybrid link drift: concept " + cid + " is fully taught in a later phase than consumer " + firstStep + " (a preview covers the dependency)");
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
348
466
|
pushEdge(cid, firstStep, str(l.relationship, "hybrid link") + " [" + depth + "]");
|
|
349
467
|
for (const n of nodes) {
|
|
350
468
|
if (n.kind === "concept" && n.concept_ref === cid && n.introduce_aspect === "advanced" && n.phase_id === str(l.phase_id)) {
|
|
@@ -363,6 +481,21 @@ function emitFromHybrid(hybrid, opts) {
|
|
|
363
481
|
for (const k of n.keywords?.prerequisite ?? []) {
|
|
364
482
|
const src = introducer.get(k.toLowerCase());
|
|
365
483
|
if (!src || src === n.id) continue;
|
|
484
|
+
const srcNode = nodes.find((x) => x.id === src);
|
|
485
|
+
const phaseOf = (id) => {
|
|
486
|
+
const n2 = nodes.find((x) => x.id === id);
|
|
487
|
+
return n2 ? emitCtx.findIndex((c) => c.id === n2.phase_id) : -1;
|
|
488
|
+
};
|
|
489
|
+
const conceptOvertaken = n.kind === "concept" && srcNode?.kind === "product_step";
|
|
490
|
+
const fromPhase = phaseOf(src);
|
|
491
|
+
const toPhase = phaseOf(n.id);
|
|
492
|
+
if (conceptOvertaken || emitCtx.length > 0 && fromPhase > toPhase) {
|
|
493
|
+
pushWarning(
|
|
494
|
+
opts,
|
|
495
|
+
"keyword-order drift: introducer " + src + " sits in a later phase than consumer " + n.id + ' (keyword "' + k + '") \u2014 host should move the introducer earlier'
|
|
496
|
+
);
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
366
499
|
if (feedOrder.get(src) < feedOrder.get(n.id)) pushEdge(src, n.id, "keyword prerequisite [" + k + "]");
|
|
367
500
|
}
|
|
368
501
|
}
|
|
@@ -935,8 +1068,8 @@ var ProjectConceptLinkSchema = zod.z.object({
|
|
|
935
1068
|
});
|
|
936
1069
|
var ConceptIntroductionSchema = zod.z.object({
|
|
937
1070
|
concept_id: zod.z.string().describe("Concept ID from knowledge_graph"),
|
|
938
|
-
aspect: zod.z.enum(["new", "advanced"]).default("new").describe(
|
|
939
|
-
"new = concept introduced for the first time; advanced = previously introduced concept revisited at higher depth"
|
|
1071
|
+
aspect: zod.z.enum(["new", "advanced", "preview"]).default("new").describe(
|
|
1072
|
+
"new = concept introduced for the first time; advanced = previously introduced concept revisited at higher depth; preview = light ULO awareness pass ('know it exists') placed at the consuming phase BEFORE the full introduction \u2014 the anchor phase still owns the full 'new' teach"
|
|
940
1073
|
),
|
|
941
1074
|
note: zod.z.string().optional().default("").describe("Which advanced aspect of the concept this phase develops")
|
|
942
1075
|
});
|
|
@@ -4925,6 +5058,8 @@ function auditPhasePlan(plan, features, concepts, links, warnings, log) {
|
|
|
4925
5058
|
const phases = [];
|
|
4926
5059
|
const featurePhase = /* @__PURE__ */ new Map();
|
|
4927
5060
|
const newIntroPhase = /* @__PURE__ */ new Map();
|
|
5061
|
+
const previewsSeen = /* @__PURE__ */ new Set();
|
|
5062
|
+
const previewPhase = /* @__PURE__ */ new Map();
|
|
4928
5063
|
const errors = [];
|
|
4929
5064
|
plan.forEach((rp, idx) => {
|
|
4930
5065
|
const id = String(rp.id || "PH" + (idx + 1));
|
|
@@ -4956,7 +5091,22 @@ function auditPhasePlan(plan, features, concepts, links, warnings, log) {
|
|
|
4956
5091
|
errors.push("Phase " + id + ": introduces unknown concept " + cid);
|
|
4957
5092
|
continue;
|
|
4958
5093
|
}
|
|
4959
|
-
const
|
|
5094
|
+
const rawAspect = String(ri.aspect || "new");
|
|
5095
|
+
const aspect = rawAspect === "advanced" || rawAspect === "preview" ? rawAspect : "new";
|
|
5096
|
+
if (aspect === "preview") {
|
|
5097
|
+
if (newIntroPhase.has(cid)) {
|
|
5098
|
+
errors.push("Phase " + id + ": preview of " + cid + " after its new introduction in phase " + newIntroPhase.get(cid) + " - preview must precede the anchor teach");
|
|
5099
|
+
continue;
|
|
5100
|
+
}
|
|
5101
|
+
if (previewsSeen.has(cid)) {
|
|
5102
|
+
errors.push("Phase " + id + ": duplicate preview of " + cid);
|
|
5103
|
+
continue;
|
|
5104
|
+
}
|
|
5105
|
+
previewsSeen.add(cid);
|
|
5106
|
+
previewPhase.set(cid, order);
|
|
5107
|
+
introductions.push({ concept_id: cid, aspect, note: String(ri.note || "") });
|
|
5108
|
+
continue;
|
|
5109
|
+
}
|
|
4960
5110
|
if (aspect === "advanced") {
|
|
4961
5111
|
const first = newIntroPhase.get(cid);
|
|
4962
5112
|
if (first === void 0) {
|
|
@@ -5004,10 +5154,17 @@ function auditPhasePlan(plan, features, concepts, links, warnings, log) {
|
|
|
5004
5154
|
}
|
|
5005
5155
|
for (const [cid, consumerOrder] of firstConsumerPhase) {
|
|
5006
5156
|
const intro = newIntroPhase.get(cid);
|
|
5007
|
-
|
|
5157
|
+
const prev = previewPhase.get(cid);
|
|
5158
|
+
if (intro === void 0 && prev === void 0) {
|
|
5008
5159
|
errors.push("Concept " + cid + " is consumed from phase " + consumerOrder + " but never introduced in any phase");
|
|
5009
|
-
} else if (intro > consumerOrder) {
|
|
5010
|
-
errors.push("Concept " + cid + " introduced in phase " + intro + " but first consumed in phase " + consumerOrder + " - introduction must come no later than first consumption");
|
|
5160
|
+
} else if (intro !== void 0 && intro > consumerOrder && (prev === void 0 || prev > consumerOrder)) {
|
|
5161
|
+
errors.push("Concept " + cid + " introduced in phase " + intro + " but first consumed in phase " + consumerOrder + " - introduction must come no later than first consumption (or a preview must cover the dependency)");
|
|
5162
|
+
}
|
|
5163
|
+
}
|
|
5164
|
+
for (const [cid, pOrder] of previewPhase) {
|
|
5165
|
+
const anchor = newIntroPhase.get(cid);
|
|
5166
|
+
if (anchor !== void 0 && anchor <= pOrder) {
|
|
5167
|
+
errors.push("Concept " + cid + " previewed in phase " + pOrder + " but fully introduced in phase " + anchor + " - preview must precede the anchor introduction");
|
|
5011
5168
|
}
|
|
5012
5169
|
}
|
|
5013
5170
|
return { phases, errors };
|
|
@@ -5023,7 +5180,7 @@ async function decomposePhases(args) {
|
|
|
5023
5180
|
const linkList = links.map(
|
|
5024
5181
|
(l) => "- " + l.feature_id + " -> " + l.concept_id + " (" + l.depth + ")"
|
|
5025
5182
|
).join("\n") || "(none)";
|
|
5026
|
-
const systemPrompt =
|
|
5183
|
+
const systemPrompt = 'You decompose a software project build into PROGRESSIVE COMPLETION PHASES for learning purposes.\n\nA phase is NOT a feature and NOT a milestone list: it is a cross-feature slice of the\nproduct whose completion yields a DEMONSTRABLY more complete product. Build up gradually:\nthe product grows feature by feature across phases, and each phase adds its features to\nwhat previous phases already built.\n\nRULES:\n1. Every feature must be assigned to EXACTLY ONE phase (no feature reused, none skipped).\n2. Phases are ordered; later phases depend on earlier ones and yield a more complete product.\n3. product_completion describes concretely what the product can DO once the phase is done.\n4. introduces lists which concepts the phase must teach BEFORE its feature work starts:\n - aspect new: first time the concept appears in the course\n - aspect advanced: a concept introduced in an EARLIER phase, revisited here at a\n higher depth (an advanced aspect of the same concept, e.g. validation rules on top\n of basic data modeling). Use the note field to say which aspect.\n - aspect preview: a light awareness pass ("know it exists", ULO depth only, ~5 min)\n placed in an EARLIER phase when its feature work needs the vocabulary before the\n full teach. The anchor phase still owns the full new introduction.\n5. A concept MUST be introduced (new) no later than the first phase that consumes it.\n6. A concept must not be introduced before its own prerequisites are introduced.\n7. Typically 3-6 phases for a small project; keep phases balanced.\n8. Phase 1 usually covers project setup/foundation features plus the first minimal slice.\n9. Return JSON only.';
|
|
5027
5184
|
const baseUserPrompt = "FEATURES:\n" + featureList + "\n\nCONCEPTS:\n" + conceptList + "\n\nFEATURE-CONCEPT LINKS:\n" + linkList + "\n\nReturn JSON with a phases array. Each phase: { id: PH1, name, product_completion, feature_ids: [F0, F1], introduces: [{ concept_id: C1, aspect: new or advanced, note }] }.\n";
|
|
5028
5185
|
const MAX_DECOMPOSE_ATTEMPTS = 3;
|
|
5029
5186
|
let auditErrors = [];
|
|
@@ -6094,6 +6251,7 @@ exports.WiringSchema = WiringSchema;
|
|
|
6094
6251
|
exports.assembleRoadmap = assembleRoadmap;
|
|
6095
6252
|
exports.assignConceptCodes = assignConceptCodes;
|
|
6096
6253
|
exports.auditDepthLayers = auditDepthLayers;
|
|
6254
|
+
exports.auditPhasePlan = auditPhasePlan;
|
|
6097
6255
|
exports.auditSyllabusCoverage = auditSyllabusCoverage;
|
|
6098
6256
|
exports.breakPrerequisiteCycles = breakPrerequisiteCycles;
|
|
6099
6257
|
exports.cioActionSlug = cioActionSlug;
|