canvas-design-mcp 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CLAUDE.md +200 -0
  2. package/DESIGN.md +288 -0
  3. package/PROFESSOR-INSTRUCTIONS.txt +131 -0
  4. package/README.md +250 -0
  5. package/dist/canvas-api.d.ts +24 -0
  6. package/dist/canvas-api.d.ts.map +1 -0
  7. package/dist/canvas-api.js +146 -0
  8. package/dist/canvas-api.js.map +1 -0
  9. package/dist/config.d.ts +5 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +22 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/design-engine.d.ts +5 -0
  14. package/dist/design-engine.d.ts.map +1 -0
  15. package/dist/design-engine.js +23 -0
  16. package/dist/design-engine.js.map +1 -0
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +567 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/tools/accessibility.d.ts +7 -0
  22. package/dist/tools/accessibility.d.ts.map +1 -0
  23. package/dist/tools/accessibility.js +149 -0
  24. package/dist/tools/accessibility.js.map +1 -0
  25. package/dist/tools/contrast.d.ts +2 -0
  26. package/dist/tools/contrast.d.ts.map +1 -0
  27. package/dist/tools/contrast.js +7 -0
  28. package/dist/tools/contrast.js.map +1 -0
  29. package/dist/tools/critique.d.ts +23 -0
  30. package/dist/tools/critique.d.ts.map +1 -0
  31. package/dist/tools/critique.js +194 -0
  32. package/dist/tools/critique.js.map +1 -0
  33. package/dist/tools/generate.d.ts +18 -0
  34. package/dist/tools/generate.d.ts.map +1 -0
  35. package/dist/tools/generate.js +101 -0
  36. package/dist/tools/generate.js.map +1 -0
  37. package/dist/tools/gotchas.d.ts +7 -0
  38. package/dist/tools/gotchas.d.ts.map +1 -0
  39. package/dist/tools/gotchas.js +61 -0
  40. package/dist/tools/gotchas.js.map +1 -0
  41. package/dist/tools/ingest.d.ts +44 -0
  42. package/dist/tools/ingest.d.ts.map +1 -0
  43. package/dist/tools/ingest.js +211 -0
  44. package/dist/tools/ingest.js.map +1 -0
  45. package/dist/tools/list-courses.d.ts +16 -0
  46. package/dist/tools/list-courses.d.ts.map +1 -0
  47. package/dist/tools/list-courses.js +79 -0
  48. package/dist/tools/list-courses.js.map +1 -0
  49. package/dist/tools/page-io.d.ts +19 -0
  50. package/dist/tools/page-io.d.ts.map +1 -0
  51. package/dist/tools/page-io.js +77 -0
  52. package/dist/tools/page-io.js.map +1 -0
  53. package/dist/tools/panopto.d.ts +36 -0
  54. package/dist/tools/panopto.d.ts.map +1 -0
  55. package/dist/tools/panopto.js +188 -0
  56. package/dist/tools/panopto.js.map +1 -0
  57. package/dist/tools/personas.d.ts +21 -0
  58. package/dist/tools/personas.d.ts.map +1 -0
  59. package/dist/tools/personas.js +464 -0
  60. package/dist/tools/personas.js.map +1 -0
  61. package/dist/tools/philosophy.d.ts +21 -0
  62. package/dist/tools/philosophy.d.ts.map +1 -0
  63. package/dist/tools/philosophy.js +137 -0
  64. package/dist/tools/philosophy.js.map +1 -0
  65. package/dist/tools/publish.d.ts +31 -0
  66. package/dist/tools/publish.d.ts.map +1 -0
  67. package/dist/tools/publish.js +198 -0
  68. package/dist/tools/publish.js.map +1 -0
  69. package/dist/tools/redesign.d.ts +18 -0
  70. package/dist/tools/redesign.d.ts.map +1 -0
  71. package/dist/tools/redesign.js +68 -0
  72. package/dist/tools/redesign.js.map +1 -0
  73. package/dist/tools/update-kb.d.ts +10 -0
  74. package/dist/tools/update-kb.d.ts.map +1 -0
  75. package/dist/tools/update-kb.js +93 -0
  76. package/dist/tools/update-kb.js.map +1 -0
  77. package/dist/tools/validate.d.ts +10 -0
  78. package/dist/tools/validate.d.ts.map +1 -0
  79. package/dist/tools/validate.js +76 -0
  80. package/dist/tools/validate.js.map +1 -0
  81. package/dist/types.d.ts +65 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +2 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/wizard.d.ts +3 -0
  86. package/dist/wizard.d.ts.map +1 -0
  87. package/dist/wizard.js +229 -0
  88. package/dist/wizard.js.map +1 -0
  89. package/docs/canvas-design-kb/00-meta/Changelog.md +42 -0
  90. package/docs/canvas-design-kb/00-meta/Contributing.md +58 -0
  91. package/docs/canvas-design-kb/00-meta/KB-Overview.md +51 -0
  92. package/docs/canvas-design-kb/01-canvas-rce/CSS-Inline-Strategy.md +166 -0
  93. package/docs/canvas-design-kb/01-canvas-rce/Canvas-Built-In-CSS-Classes.md +243 -0
  94. package/docs/canvas-design-kb/01-canvas-rce/Canvas-Page-Types.md +59 -0
  95. package/docs/canvas-design-kb/01-canvas-rce/HTML-Allowlist.md +204 -0
  96. package/docs/canvas-design-kb/01-canvas-rce/RCE-Limitations-and-Workarounds.md +151 -0
  97. package/docs/canvas-design-kb/01-canvas-rce/RCE-Overview.md +92 -0
  98. package/docs/canvas-design-kb/02-design-md/DESIGN-MD-Canvas-Template.md +323 -0
  99. package/docs/canvas-design-kb/02-design-md/DESIGN-MD-File-Structure.md +245 -0
  100. package/docs/canvas-design-kb/02-design-md/DESIGN-MD-Overview.md +120 -0
  101. package/docs/canvas-design-kb/02-design-md/DESIGN-MD-Toolchain.md +234 -0
  102. package/docs/canvas-design-kb/03-design-systems/Color-and-Typography.md +146 -0
  103. package/docs/canvas-design-kb/03-design-systems/Component-Library.md +299 -0
  104. package/docs/canvas-design-kb/03-design-systems/Design-System-Principles.md +99 -0
  105. package/docs/canvas-design-kb/04-tools/Canvas-Theme-Editor.md +40 -0
  106. package/docs/canvas-design-kb/04-tools/Other-Canvas-Design-Tools.md +47 -0
  107. package/docs/canvas-design-kb/05-patterns/Course-Home-Page.md +224 -0
  108. package/docs/canvas-design-kb/06-accessibility/Accessibility-Overview.md +128 -0
  109. package/docs/canvas-design-kb/07-resources/Inspiration-and-Showcases.md +121 -0
  110. package/docs/canvas-design-kb/07-resources/Official-Canvas-Links.md +54 -0
  111. package/docs/canvas-design-kb/README.md +58 -0
  112. package/docs/feature-roadmap.md +123 -0
  113. package/docs/installation.md +340 -0
  114. package/package.json +45 -0
  115. package/scripts/deploy-public.ps1 +68 -0
  116. package/src/kb/design-principles.md +45 -0
  117. package/src/templates/ignite-assignment-page.html +203 -0
  118. package/src/templates/two-column-dashboard.html +33 -0
@@ -0,0 +1,464 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join, dirname } from 'node:path';
4
+ export const PERSONAS_PATH = join(homedir(), '.canvas-design-mcp', 'student-personas.md');
5
+ export const PERSONAS_TEMPLATE = '# Student Personas\n\nNo personas generated yet. Call generate_student_personas to create a set.\n';
6
+ // Race/Ethnic Background — real population distribution from Student-Personas.md
7
+ export const RACE_TABLE = [
8
+ { cumulative: 0.578, value: 'White' },
9
+ { cumulative: 0.765, value: 'Hispanic/Latino' },
10
+ { cumulative: 0.886, value: 'Black' },
11
+ { cumulative: 0.945, value: 'Asian' },
12
+ { cumulative: 0.956, value: 'Native American' },
13
+ { cumulative: 0.958, value: 'Native Pacific Islander' },
14
+ { cumulative: 0.969, value: 'Mixed Race (White and Black)' },
15
+ { cumulative: 0.977, value: 'Mixed Race (Asian and White)' },
16
+ { cumulative: 0.982, value: 'Mixed Race (Native American and Hispanic/Latino)' },
17
+ { cumulative: 0.990, value: 'Mixed Race (Black and Hispanic/Latino)' },
18
+ { cumulative: 0.996, value: 'Mixed Race (Asian and Black)' },
19
+ { cumulative: 1.000, value: 'Adopted (choose race of student and family)' },
20
+ ];
21
+ // Learning Disabilities/Challenges — real prevalence distribution from Student-Personas.md
22
+ export const DISABILITY_TABLE = [
23
+ { cumulative: 0.61, value: 'None' },
24
+ { cumulative: 0.70, value: 'ADHD' },
25
+ { cumulative: 0.76, value: 'Dyslexia' },
26
+ { cumulative: 0.81, value: 'Speech Impediment' },
27
+ { cumulative: 0.85, value: 'Anxiety' },
28
+ { cumulative: 0.89, value: 'Dysgraphia' },
29
+ { cumulative: 0.93, value: 'Mild Dyslexia' },
30
+ { cumulative: 0.96, value: 'Mild Anxiety' },
31
+ { cumulative: 0.98, value: 'Visual Processing Disorder' },
32
+ { cumulative: 0.998, value: 'Hearing Impairment' },
33
+ { cumulative: 1.000, value: 'Memory Retention Challenges' },
34
+ ];
35
+ // The 21 non-weighted dimensions. Values sourced from AI-Personas-ideas_Student-Personas.csv,
36
+ // deduplicated and lightly cleaned. Uniform random selection (each value equally likely).
37
+ export const DIMENSION_POOLS = {
38
+ age: [
39
+ '18-year-old freshman',
40
+ '19-year-old sophomore',
41
+ '20-year-old sophomore',
42
+ '21-year-old sophomore',
43
+ '22-year-old senior',
44
+ '23-year-old junior',
45
+ '24-year-old graduate student',
46
+ '26-year-old junior',
47
+ '28-year-old PhD candidate',
48
+ '30-year-old returning student',
49
+ '32-year-old first-year law student',
50
+ '35-year-old MBA student',
51
+ ],
52
+ familySituation: [
53
+ 'Single with no dependents',
54
+ 'Married, no children',
55
+ 'Single parent with two kids',
56
+ 'Engaged, no children',
57
+ 'Married with a toddler',
58
+ 'Living with parents',
59
+ 'Divorced with shared custody',
60
+ 'Lives on campus, single',
61
+ 'Single, caregiver for a sibling',
62
+ 'Lives with partner',
63
+ 'Lives on campus; supportive parents, one younger sibling',
64
+ 'Lives off-campus with roommates; close-knit family, one older sibling',
65
+ 'Lives at home with supportive parents who own a small business',
66
+ 'Married with two young children; supportive spouse',
67
+ 'Lives at home with working-class immigrant parents and younger siblings',
68
+ 'Lives off-campus with roommates; supportive parents, only child',
69
+ ],
70
+ workStudyBalance: [
71
+ 'Full-time student, no job',
72
+ 'Part-time job, full-time student',
73
+ 'Full-time job, part-time student',
74
+ 'Research assistant, full-time student',
75
+ 'Part-time retail job, full-time student',
76
+ 'Full-time job, night classes',
77
+ 'Student-athlete, full-time',
78
+ 'Full-time student with part-time campus job (10 hrs/week)',
79
+ 'Full-time student, volunteers 5–8 hours/week',
80
+ 'Full-time student with an online side business (15–20 hrs/week)',
81
+ 'Part-time student (9 credits), works full-time (40 hrs/week)',
82
+ 'Full-time student, works part-time to contribute to household income',
83
+ ],
84
+ previousEducation: [
85
+ 'High school valedictorian',
86
+ 'GED recipient',
87
+ 'Some college, no degree',
88
+ 'Undergraduate degree in sociology',
89
+ 'Associate degree completed',
90
+ 'Top 10% in high school',
91
+ 'Community college transfer',
92
+ "Bachelor's degree in business",
93
+ "Master's in biology",
94
+ 'Homeschooled background',
95
+ "Bachelor's in history; returning after a gap",
96
+ 'Graduated high school with honors; strong STEM focus, multiple AP credits',
97
+ 'High school diploma with 3.8 GPA; active in debate and student government',
98
+ 'High school diploma; vocational courses in graphic design, self-taught in e-commerce',
99
+ 'First in family to attend college; high school diploma with a 3.5 GPA',
100
+ 'No prior college experience; first-generation college student',
101
+ ],
102
+ subjectStrengths: [
103
+ 'Strong in science',
104
+ 'Excels in English',
105
+ 'Good with math',
106
+ 'Skilled in research methods',
107
+ 'Good at presentations',
108
+ 'Strong in history',
109
+ 'Financial analysis',
110
+ 'Data analysis',
111
+ 'Creative writing',
112
+ 'Logic and reasoning',
113
+ 'Social studies',
114
+ 'Mathematics, physics, and computer programming',
115
+ 'Writing, sociology, political science, and critical analysis',
116
+ 'Graphic design, marketing, and digital media',
117
+ 'English composition, literature, and communication',
118
+ 'Advanced programming, data structures, and algorithms',
119
+ ],
120
+ subjectWeaknesses: [
121
+ 'Struggles with math',
122
+ 'Weak in science',
123
+ 'Struggles with literature',
124
+ 'Struggles with statistics',
125
+ 'Weak in analytical writing',
126
+ 'Struggles in public speaking',
127
+ 'Struggles with creative tasks',
128
+ 'Weak in technical writing',
129
+ 'Struggles with sustained focus',
130
+ 'Essay writing and public speaking',
131
+ 'Statistics and advanced mathematics',
132
+ 'Advanced calculus and complex scientific theories',
133
+ 'Adapting to new technology platforms',
134
+ 'Advanced mathematics and academic vocabulary',
135
+ ],
136
+ academicConfidence: [
137
+ 'Highly confident',
138
+ 'Moderate confidence',
139
+ 'Low confidence',
140
+ 'Growing confidence',
141
+ 'Very high confidence',
142
+ 'Confident in technical skills',
143
+ 'Building confidence after setbacks',
144
+ 'High in STEM, moderate in humanities',
145
+ 'High in discussions and writing',
146
+ 'High in creative work, lower in traditional exam settings',
147
+ 'Moderate; sometimes experiences imposter syndrome',
148
+ 'High, particularly in problem-solving and coding',
149
+ ],
150
+ shortTermGoals: [
151
+ 'Pass the class with an A',
152
+ 'Understand key concepts deeply',
153
+ 'Complete all assignments on time',
154
+ 'Publish a research finding',
155
+ 'Improve analytical writing skills',
156
+ 'Improve public speaking skills',
157
+ 'Apply course material directly to current job',
158
+ 'Pass the class with a solid grade',
159
+ 'Balance athletics and academics',
160
+ 'Maintain a 3.8 GPA and join a club',
161
+ 'Get an A in research methods and secure an internship',
162
+ 'Pass all prerequisites and get comfortable with online learning',
163
+ 'Maintain a 3.0 GPA and start using tutoring services',
164
+ 'Complete a capstone project and secure a job offer',
165
+ ],
166
+ longTermGoals: [
167
+ 'Aspires to be a doctor',
168
+ 'Interested in teaching at the secondary level',
169
+ 'Undecided; exploring options',
170
+ 'Wants to become a professor',
171
+ 'Aspires to manage a team in industry',
172
+ 'Planning to go to law school',
173
+ 'Aims to work in data science',
174
+ 'Seeks executive-level roles',
175
+ 'Academic research career',
176
+ 'Aspires to be a lawyer',
177
+ 'Interested in sports management',
178
+ 'Electrical engineer; tech company or renewable energy',
179
+ 'Policy analyst and social justice advocate',
180
+ 'Full-time entrepreneur and creative director',
181
+ 'Registered Nurse specializing in pediatrics or critical care',
182
+ 'Teacher or social worker',
183
+ 'Software engineer, data scientist, or cybersecurity specialist',
184
+ ],
185
+ confidenceLevels: [
186
+ 'High confidence overall',
187
+ 'Moderate confidence',
188
+ 'Low confidence; working to overcome self-doubt',
189
+ 'Very confident',
190
+ 'Confidence varies day-to-day',
191
+ 'Confident in academics but not social situations',
192
+ 'High, particularly in intellectual abilities',
193
+ 'High in group settings and when expressing opinions',
194
+ 'High in entrepreneurial and artistic skills; lower facing academic setbacks',
195
+ 'Building; initially low due to long break from academia',
196
+ 'Growing; gaining confidence with each small success in college',
197
+ ],
198
+ learningMotivation: [
199
+ 'Passionate about the subject',
200
+ 'Focused on earning the degree',
201
+ 'Driven by career advancement',
202
+ 'Wants a higher salary',
203
+ 'Wants to build a professional network',
204
+ 'Driven by personal curiosity',
205
+ 'Learning for personal growth',
206
+ 'Passionate about social justice',
207
+ 'Driven by athletic and competitive goals',
208
+ 'Intrinsic; curiosity and desire to build and innovate',
209
+ 'Intrinsic; passionate about social change',
210
+ 'Intrinsic; creativity and desire to build a business',
211
+ 'Extrinsic initially (career prospects), with growing intrinsic interest in the field',
212
+ 'Mix of extrinsic (support family) and intrinsic (personal growth)',
213
+ ],
214
+ engagementStyle: [
215
+ 'Proactive; asks clarifying questions',
216
+ 'Observant and reserved',
217
+ 'Active in online discussions',
218
+ 'Prefers working independently',
219
+ 'Rarely participates in open discussion',
220
+ 'Highly engaged; sits at the front',
221
+ 'Prefers small group discussions',
222
+ 'Observes and participates occasionally',
223
+ 'Proactive researcher; finds primary sources independently',
224
+ 'Rarely speaks up in class; more comfortable in writing',
225
+ 'Prefers debate and structured discussion',
226
+ 'Enjoys team-based activities and collaborative projects',
227
+ 'Engages actively in labs and problem-solving; asks clarifying questions in lectures',
228
+ 'Participates frequently in discussions; enjoys debates',
229
+ 'Engages most in project-based courses; quieter in traditional lectures',
230
+ 'Attentive listener; prefers to absorb information before contributing',
231
+ 'Asks questions in smaller groups or during office hours rather than in lecture',
232
+ ],
233
+ preferredLearningMethods: [
234
+ 'Hands-on activities and experimentation',
235
+ 'Visual aids and diagrams',
236
+ 'Reading textbooks and articles',
237
+ 'Listening to lectures',
238
+ 'Group activities and peer discussion',
239
+ 'Video tutorials',
240
+ 'Case studies and real-world examples',
241
+ 'Research papers and primary sources',
242
+ 'Written outlines and structured notes',
243
+ 'Hands-on labs, problem sets, and online tutorials',
244
+ 'Scholarly articles, group discussions, and writing essays',
245
+ 'Visual demonstrations, workshops, and learning by doing',
246
+ 'Online modules, practical examples, and self-paced learning',
247
+ 'One-on-one tutoring, structured lessons, and clear outlines',
248
+ ],
249
+ technologyComfortLevel: [
250
+ 'Very comfortable; adopts new tools quickly',
251
+ 'Prefers traditional in-person methods',
252
+ 'Comfortable with common online resources',
253
+ 'Advanced tech skills across multiple platforms',
254
+ 'Adequate; manages required tools with some effort',
255
+ 'Enjoys using digital tools to organize work',
256
+ 'Tech-savvy and adaptive to new platforms',
257
+ 'Expert in domain-specific scientific software',
258
+ 'Basic tech skills; needs help with new systems',
259
+ 'Proficient with legal and research databases',
260
+ 'Extremely high; proficient with multiple programming languages and engineering tools',
261
+ 'High; comfortable with research databases and online collaboration tools',
262
+ 'High; adept at graphic design software and social media marketing tools',
263
+ 'Moderate; comfortable with Word and email, needs guidance with new platforms',
264
+ 'Moderate; comfortable with basic computer use, needs help with specialized software',
265
+ ],
266
+ academicSupport: [
267
+ 'Access to a peer study group',
268
+ 'Tutors available through the institution',
269
+ 'Limited access to support services',
270
+ 'Utilizes peer study groups independently',
271
+ 'Online tutoring available',
272
+ 'Peer-led study group',
273
+ 'Attends office hours regularly',
274
+ 'Mentorship program through the department',
275
+ 'Research group support from faculty',
276
+ 'University-provided tutors',
277
+ 'Writing center and faculty office hours',
278
+ 'Access to specialized labs, research opportunities, and peer study groups',
279
+ 'Undergraduate research opportunities, writing center, and faculty mentorship',
280
+ 'Mentorship from professors in creative fields and business advising',
281
+ 'Academic advising, writing center, and technology support for online learning',
282
+ 'Tutoring in math and science, financial aid counseling, and academic coaching',
283
+ ],
284
+ emotionalSupport: [
285
+ 'Strong support from family',
286
+ 'Encouragement from close friends',
287
+ 'Relies on community and faith support',
288
+ 'Supportive partner',
289
+ 'Finds motivation from academic peers',
290
+ 'Relies on family support from home',
291
+ 'Spouse is a strong emotional anchor',
292
+ 'Close-knit group of college friends',
293
+ 'Strong connection to cultural community',
294
+ 'Friends with shared academic interests; uses sports and hobbies for stress relief',
295
+ 'Close friends; self-care practices and occasional counseling',
296
+ 'Creative community and understanding family; practices stress management',
297
+ 'Strong support from spouse and family; peer group of non-traditional students',
298
+ 'Family support, mentorship from older students and faculty, community resources',
299
+ ],
300
+ culturalBackground: [
301
+ 'First-generation college student',
302
+ 'Bilingual; embraces cultural diversity',
303
+ 'Military family background',
304
+ 'International student background',
305
+ 'Native American background influences worldview',
306
+ 'Suburban middle-class upbringing',
307
+ 'From an underrepresented community in higher education',
308
+ 'Urban upper-middle-class background',
309
+ 'Diverse international cultural perspectives',
310
+ 'Rural background; first in family to leave the region for school',
311
+ 'Ethnic minority; navigates a predominantly white institution',
312
+ 'Suburban middle-income; values practicality and hard work',
313
+ 'Strong emphasis on education and family values',
314
+ 'Values social justice and intellectual discourse',
315
+ 'Strong family ties; celebrates cultural heritage through art and food',
316
+ 'Midwestern; values hard work and self-reliance',
317
+ 'Close-knit community; values resilience, often first in family to pursue higher education',
318
+ ],
319
+ financialSituation: [
320
+ 'Financially stable; family covers tuition',
321
+ 'Needs to work part-time to cover expenses',
322
+ 'Receiving financial aid; budget is tight',
323
+ 'Financially independent; self-sufficient',
324
+ 'Works to afford child care alongside school',
325
+ 'Financially supported by family',
326
+ 'Self-funded entirely through part-time work',
327
+ 'Well-compensated in current career; returning to school',
328
+ 'Funded through grants and scholarships',
329
+ 'Uses student loans for tuition; manages debt carefully',
330
+ 'Financially strained; unexpected expenses are a major risk',
331
+ 'Relies on a scholarship; cannot afford to lose it',
332
+ 'Comfortable; tuition covered by parents, part-time job for spending money',
333
+ 'Stable; some financial aid, parents provide supplemental support',
334
+ 'Variable; relies on business income and some parental support',
335
+ 'Strained; relies on financial aid and full-time work, manages a very tight budget',
336
+ 'Strained; relies heavily on financial aid, often helps support family financially',
337
+ ],
338
+ responsivenessToFeedback: [
339
+ 'Actively seeks out feedback',
340
+ 'Handles feedback well without defensiveness',
341
+ 'Appreciates constructive feedback when it is specific',
342
+ 'Values feedback primarily from professors',
343
+ 'Finds critical feedback difficult to process emotionally',
344
+ 'Open to feedback from any source',
345
+ 'Welcomes constructive criticism and acts on it quickly',
346
+ 'Enjoys feedback as a tool to refine skills',
347
+ 'Feedback-driven; tracks progress against prior critiques',
348
+ 'Finds feedback motivating; uses it to set new goals',
349
+ 'Values detailed, written feedback over verbal comments',
350
+ 'Highly responsive; seeks feedback to improve and refine understanding',
351
+ 'Very responsive; thrives on constructive criticism to strengthen arguments',
352
+ 'Responsive in creative critiques; can be sensitive to purely subjective criticism',
353
+ 'Highly responsive; eager to learn, seeks clear and actionable feedback',
354
+ 'Responsive, but hesitant to ask for clarification; benefits from explicit encouragement',
355
+ ],
356
+ growthMindset: [
357
+ 'Open to learning from mistakes',
358
+ 'Growth-oriented; embraces challenges',
359
+ 'Shows perseverance through setbacks',
360
+ 'Views setbacks as learning opportunities',
361
+ 'Willing to try new strategies when stuck',
362
+ 'Always seeks ways to improve',
363
+ 'Sees challenges as chances to grow',
364
+ 'Highly resilient and adaptive',
365
+ 'Passionate about continuous self-improvement',
366
+ 'Seeks gradual, steady improvement over time',
367
+ 'Strong growth mindset; views challenges as opportunities to develop new skills',
368
+ 'Strong growth mindset; actively seeks new knowledge and changing perspectives',
369
+ 'Strong growth mindset; constantly iterating on ideas and learning from failures',
370
+ 'Strong growth mindset; determined to master new subjects returning to school',
371
+ 'Developing growth mindset; working to overcome self-doubt and embrace learning',
372
+ ],
373
+ timeManagement: [
374
+ 'Balances school and social life well',
375
+ 'Struggles to meet deadlines consistently',
376
+ 'Must juggle work, children, and school simultaneously',
377
+ 'Organized and plans ahead reliably',
378
+ 'Finds it hard to stay organized without structure',
379
+ 'Easily distracted; struggles with long reading assignments',
380
+ 'Manages time effectively; rarely behind',
381
+ 'Tight schedule; well-organized with strict routines',
382
+ 'Juggles research and coursework with few conflicts',
383
+ 'Sometimes misses deadlines during high-stress periods',
384
+ 'Tightly manages limited time; little room for error',
385
+ 'Needs flexibility in deadlines due to unpredictable schedule',
386
+ 'Excellent; uses a digital planner, schedules study blocks, rarely procrastinates',
387
+ 'Very good; balances academics, volunteering, and social life with a detailed planner',
388
+ 'Variable; prioritizes business tasks, sometimes sacrifices sleep for schoolwork',
389
+ 'Excellent; highly organized due to family and work commitments, uses strict schedules',
390
+ 'Challenged; struggles with balancing work, family obligations, and studies',
391
+ ],
392
+ };
393
+ // Compare a single Math.random() draw against the cumulative table.
394
+ // The last entry must have cumulative === 1.0 to guarantee a match.
395
+ export function weightedSample(table) {
396
+ const r = Math.random();
397
+ for (const entry of table) {
398
+ if (r < entry.cumulative)
399
+ return entry.value;
400
+ }
401
+ return table[table.length - 1].value;
402
+ }
403
+ // Uniform random pick from an array. All values are equally likely.
404
+ export function poolSample(pool) {
405
+ return pool[Math.floor(Math.random() * pool.length)];
406
+ }
407
+ function ensureDir(filePath) {
408
+ const dir = dirname(filePath);
409
+ if (!existsSync(dir))
410
+ mkdirSync(dir, { recursive: true });
411
+ }
412
+ // Samples all 23 dimensions and formats one persona as a Markdown section.
413
+ // index is 1-based (Persona 1, Persona 2, ...).
414
+ function buildPersona(index) {
415
+ return [
416
+ `## Persona ${index}`,
417
+ '',
418
+ `- **Age:** ${poolSample(DIMENSION_POOLS.age)}`,
419
+ `- **Family Situation:** ${poolSample(DIMENSION_POOLS.familySituation)}`,
420
+ `- **Work and Study Balance:** ${poolSample(DIMENSION_POOLS.workStudyBalance)}`,
421
+ `- **Previous Education:** ${poolSample(DIMENSION_POOLS.previousEducation)}`,
422
+ `- **Subject Strengths:** ${poolSample(DIMENSION_POOLS.subjectStrengths)}`,
423
+ `- **Subject Weaknesses:** ${poolSample(DIMENSION_POOLS.subjectWeaknesses)}`,
424
+ `- **Academic Confidence:** ${poolSample(DIMENSION_POOLS.academicConfidence)}`,
425
+ `- **Short-Term Goals:** ${poolSample(DIMENSION_POOLS.shortTermGoals)}`,
426
+ `- **Long-Term Goals:** ${poolSample(DIMENSION_POOLS.longTermGoals)}`,
427
+ `- **Confidence Levels:** ${poolSample(DIMENSION_POOLS.confidenceLevels)}`,
428
+ `- **Learning Motivation:** ${poolSample(DIMENSION_POOLS.learningMotivation)}`,
429
+ `- **Engagement Style:** ${poolSample(DIMENSION_POOLS.engagementStyle)}`,
430
+ `- **Preferred Learning Methods:** ${poolSample(DIMENSION_POOLS.preferredLearningMethods)}`,
431
+ `- **Technology Comfort Level:** ${poolSample(DIMENSION_POOLS.technologyComfortLevel)}`,
432
+ `- **Academic Support:** ${poolSample(DIMENSION_POOLS.academicSupport)}`,
433
+ `- **Emotional Support:** ${poolSample(DIMENSION_POOLS.emotionalSupport)}`,
434
+ `- **Cultural Background:** ${poolSample(DIMENSION_POOLS.culturalBackground)}`,
435
+ `- **Financial Situation:** ${poolSample(DIMENSION_POOLS.financialSituation)}`,
436
+ `- **Responsiveness to Feedback:** ${poolSample(DIMENSION_POOLS.responsivenessToFeedback)}`,
437
+ `- **Growth Mindset:** ${poolSample(DIMENSION_POOLS.growthMindset)}`,
438
+ `- **Time Management:** ${poolSample(DIMENSION_POOLS.timeManagement)}`,
439
+ `- **Race/Ethnic Background:** ${weightedSample(RACE_TABLE)}`,
440
+ `- **Learning Disabilities/Challenges:** ${weightedSample(DISABILITY_TABLE)}`,
441
+ ].join('\n');
442
+ }
443
+ export function generateStudentPersonas(input, personasPath = PERSONAS_PATH) {
444
+ const count = Math.min(20, Math.max(1, input.count ?? 3));
445
+ const date = new Date().toISOString().slice(0, 10);
446
+ const personas = Array.from({ length: count }, (_, i) => buildPersona(i + 1));
447
+ const content = `# Student Personas\n\nGenerated: ${date} | Count: ${count}\n\n${personas.join('\n\n')}\n`;
448
+ ensureDir(personasPath);
449
+ writeFileSync(personasPath, content, 'utf-8');
450
+ return `✓ Generated ${count} student persona${count === 1 ? '' : 's'} and saved to ${personasPath}\n\n${content}`;
451
+ }
452
+ export function getStudentPersonas(personasPath = PERSONAS_PATH) {
453
+ if (!existsSync(personasPath)) {
454
+ return { content: PERSONAS_TEMPLATE, exists: false };
455
+ }
456
+ try {
457
+ return { content: readFileSync(personasPath, 'utf-8'), exists: true };
458
+ }
459
+ catch (err) {
460
+ const message = err instanceof Error ? err.message : String(err);
461
+ throw new Error(`Cannot read student personas file: ${message}. Call generate_student_personas to rebuild.`);
462
+ }
463
+ }
464
+ //# sourceMappingURL=personas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personas.js","sourceRoot":"","sources":["../../src/tools/personas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare const PHILOSOPHY_KB_PATH: string;
2
+ export declare const PHILOSOPHY_TEMPLATE: string;
3
+ export interface GetPhilosophyKbResult {
4
+ content: string;
5
+ exists: boolean;
6
+ sections: {
7
+ hasCore: boolean;
8
+ hasCourseSpecific: boolean;
9
+ hasQuotes: boolean;
10
+ hasLectureCaptures: boolean;
11
+ };
12
+ }
13
+ export interface UpdatePhilosophyKbInput {
14
+ entry: string;
15
+ section: 'core' | 'course' | 'quotes' | 'lectures';
16
+ courseKey?: string;
17
+ }
18
+ export declare function savePhilosophyKb(content: string, kbPath?: string): void;
19
+ export declare function getPhilosophyKb(kbPath?: string): GetPhilosophyKbResult;
20
+ export declare function updatePhilosophyKb(input: UpdatePhilosophyKbInput, kbPath?: string): string;
21
+ //# sourceMappingURL=philosophy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"philosophy.d.ts","sourceRoot":"","sources":["../../src/tools/philosophy.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB,QAAmE,CAAC;AAGnG,eAAO,MAAM,mBAAmB,QAWpB,CAAC;AAeb,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,SAAS,EAAE,OAAO,CAAC;QACnB,kBAAkB,EAAE,OAAO,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAOD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAqB,GAAG,IAAI,CAGnF;AAwBD,wBAAgB,eAAe,CAAC,MAAM,SAAqB,GAAG,qBAAqB,CAclF;AAoED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAqB,GAAG,MAAM,CAmBtG"}
@@ -0,0 +1,137 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join, dirname } from 'node:path';
4
+ export const PHILOSOPHY_KB_PATH = join(homedir(), '.canvas-design-mcp', 'professor-philosophy.md');
5
+ // Saved to disk (empty sections, no placeholder prose — clean slate for detection logic)
6
+ export const PHILOSOPHY_TEMPLATE = [
7
+ '# Professor Philosophy KB',
8
+ '',
9
+ '## Core Teaching Philosophy',
10
+ '',
11
+ '## Course-Specific Focus',
12
+ '',
13
+ '## Quotes & Aphorisms',
14
+ '',
15
+ '## From Lecture Captures',
16
+ '',
17
+ ].join('\n');
18
+ // Embedded interview questions — returned to Claude when no KB file exists yet
19
+ const PHILOSOPHY_QUESTIONS_HINT = [
20
+ '*No answers yet. Ask the professor these questions one at a time to populate this section:*',
21
+ '',
22
+ '1. What\'s one thing you always tell students about this subject that you wish they\'d really internalize?',
23
+ '2. What does a student who truly gets it do differently from one who just completes the work?',
24
+ '3. What\'s the biggest mistake students make on your assignments?',
25
+ '4. What separates an A from a B in concrete terms?',
26
+ '5. Are there teaching frameworks you consciously draw from? (Bloom\'s, UDL, constructivism, andragogy, etc.)',
27
+ '6. Any quotes or sayings you use regularly in class?',
28
+ '',
29
+ ].join('\n');
30
+ function ensureDir(filePath) {
31
+ const dir = dirname(filePath);
32
+ if (!existsSync(dir))
33
+ mkdirSync(dir, { recursive: true });
34
+ }
35
+ export function savePhilosophyKb(content, kbPath = PHILOSOPHY_KB_PATH) {
36
+ ensureDir(kbPath);
37
+ writeFileSync(kbPath, content, 'utf-8');
38
+ }
39
+ function extractSectionContent(content, heading) {
40
+ const pattern = `## ${heading}`;
41
+ const idx = content.indexOf(pattern);
42
+ if (idx === -1)
43
+ return '';
44
+ const after = idx + pattern.length;
45
+ const next = content.indexOf('\n## ', after);
46
+ return next === -1 ? content.slice(after) : content.slice(after, next);
47
+ }
48
+ function detectSections(content) {
49
+ const core = extractSectionContent(content, 'Core Teaching Philosophy');
50
+ const course = extractSectionContent(content, 'Course-Specific Focus');
51
+ const quotes = extractSectionContent(content, 'Quotes & Aphorisms');
52
+ const lectures = extractSectionContent(content, 'From Lecture Captures');
53
+ return {
54
+ hasCore: core.split('\n').some(l => l.trim().length > 0),
55
+ hasCourseSpecific: course.includes('### '),
56
+ hasQuotes: quotes.split('\n').some(l => l.trim().startsWith('- ')),
57
+ hasLectureCaptures: lectures.split('\n').some(l => l.trim().startsWith('- ')),
58
+ };
59
+ }
60
+ export function getPhilosophyKb(kbPath = PHILOSOPHY_KB_PATH) {
61
+ if (!existsSync(kbPath)) {
62
+ const content = PHILOSOPHY_TEMPLATE.replace('## Core Teaching Philosophy\n', `## Core Teaching Philosophy\n\n${PHILOSOPHY_QUESTIONS_HINT}`);
63
+ return {
64
+ content,
65
+ exists: false,
66
+ sections: { hasCore: false, hasCourseSpecific: false, hasQuotes: false, hasLectureCaptures: false },
67
+ };
68
+ }
69
+ const content = readFileSync(kbPath, 'utf-8');
70
+ return { content, exists: true, sections: detectSections(content) };
71
+ }
72
+ const HEADING_MAP = {
73
+ core: 'Core Teaching Philosophy',
74
+ course: 'Course-Specific Focus',
75
+ quotes: 'Quotes & Aphorisms',
76
+ lectures: 'From Lecture Captures',
77
+ };
78
+ function formatEntry(input) {
79
+ const e = input.entry.trim();
80
+ if (input.section === 'quotes' || input.section === 'lectures') {
81
+ return e.startsWith('- ') ? e : `- ${e}`;
82
+ }
83
+ return e;
84
+ }
85
+ function appendToCourseSection(content, courseSectionAfterHeading, courseSectionEnd, courseKey, entry) {
86
+ const subsectionHeading = `### ${courseKey}`;
87
+ const subsectionIdx = content.indexOf(subsectionHeading, courseSectionAfterHeading);
88
+ if (subsectionIdx === -1 || subsectionIdx >= courseSectionEnd) {
89
+ const before = content.slice(0, courseSectionEnd).trimEnd();
90
+ const after = content.slice(courseSectionEnd);
91
+ return before + `\n\n${subsectionHeading}\n\n${entry.trim()}\n` + after;
92
+ }
93
+ const afterSub = subsectionIdx + subsectionHeading.length;
94
+ const nextSubIdx = content.indexOf('\n### ', afterSub);
95
+ const nextH2Idx = content.indexOf('\n## ', afterSub);
96
+ let subsectionEnd = courseSectionEnd;
97
+ if (nextSubIdx !== -1 && nextSubIdx < subsectionEnd)
98
+ subsectionEnd = nextSubIdx;
99
+ if (nextH2Idx !== -1 && nextH2Idx < subsectionEnd)
100
+ subsectionEnd = nextH2Idx;
101
+ const before = content.slice(0, subsectionEnd).trimEnd();
102
+ const after = content.slice(subsectionEnd);
103
+ return before + '\n' + entry.trim() + '\n' + after;
104
+ }
105
+ function appendToSection(content, input) {
106
+ const heading = HEADING_MAP[input.section];
107
+ const headingPattern = `## ${heading}`;
108
+ const headingIdx = content.indexOf(headingPattern);
109
+ if (headingIdx === -1) {
110
+ return content.trimEnd() + `\n\n## ${heading}\n\n${formatEntry(input)}\n`;
111
+ }
112
+ const afterHeading = headingIdx + headingPattern.length;
113
+ const nextH2Idx = content.indexOf('\n## ', afterHeading);
114
+ const sectionEnd = nextH2Idx === -1 ? content.length : nextH2Idx;
115
+ if (input.section === 'course') {
116
+ return appendToCourseSection(content, afterHeading, sectionEnd, input.courseKey, input.entry);
117
+ }
118
+ const entry = formatEntry(input);
119
+ const before = content.slice(0, sectionEnd).trimEnd();
120
+ const after = content.slice(sectionEnd);
121
+ return before + '\n' + entry + '\n' + after;
122
+ }
123
+ export function updatePhilosophyKb(input, kbPath = PHILOSOPHY_KB_PATH) {
124
+ if (input.section === 'course' && !input.courseKey) {
125
+ throw new Error("courseKey is required when section is 'course' — provide the course name, e.g. 'ITM 370 — AI Augmented Projects'");
126
+ }
127
+ const content = existsSync(kbPath) ? readFileSync(kbPath, 'utf-8') : PHILOSOPHY_TEMPLATE;
128
+ const updated = appendToSection(content, input);
129
+ savePhilosophyKb(updated, kbPath);
130
+ const sectionLabel = input.section === 'course' ? `Course-Specific Focus (${input.courseKey})` :
131
+ input.section === 'core' ? 'Core Teaching Philosophy' :
132
+ input.section === 'quotes' ? 'Quotes & Aphorisms' :
133
+ 'From Lecture Captures';
134
+ const preview = input.entry.length > 80 ? input.entry.slice(0, 80) + '...' : input.entry;
135
+ return `✓ Added to ${sectionLabel}: "${preview}"`;
136
+ }
137
+ //# sourceMappingURL=philosophy.js.map