connectry-architect-mcp 0.1.3 → 0.1.4
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/dist/index.js +120 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -696,44 +696,138 @@ function registerGetPracticeQuestion(server2, db2, userConfig2) {
|
|
|
696
696
|
}
|
|
697
697
|
|
|
698
698
|
// src/tools/start-assessment.ts
|
|
699
|
+
var OPTION_KEYS2 = ["A", "B", "C", "D"];
|
|
700
|
+
function buildAssessmentQuestions() {
|
|
701
|
+
const questions = [];
|
|
702
|
+
for (let d = 1; d <= 5; d++) {
|
|
703
|
+
const domainQuestions = loadQuestions(d);
|
|
704
|
+
const easy = domainQuestions.find((q) => q.difficulty === "easy");
|
|
705
|
+
const medium = domainQuestions.find((q) => q.difficulty === "medium");
|
|
706
|
+
const hard = domainQuestions.find((q) => q.difficulty === "hard");
|
|
707
|
+
if (easy) questions.push(easy);
|
|
708
|
+
if (medium) questions.push(medium);
|
|
709
|
+
if (hard) questions.push(hard);
|
|
710
|
+
}
|
|
711
|
+
return questions;
|
|
712
|
+
}
|
|
713
|
+
function formatQuestion(question, index, total) {
|
|
714
|
+
const domainNames = {
|
|
715
|
+
1: "Agentic Architecture",
|
|
716
|
+
2: "Tool Design & MCP",
|
|
717
|
+
3: "Claude Code Config",
|
|
718
|
+
4: "Prompt Engineering",
|
|
719
|
+
5: "Context & Reliability"
|
|
720
|
+
};
|
|
721
|
+
const lines = [
|
|
722
|
+
`**Assessment Question ${index + 1} of ${total}**`,
|
|
723
|
+
`Domain ${question.domainId}: ${domainNames[question.domainId] ?? "Unknown"} | ${question.difficulty}`,
|
|
724
|
+
"",
|
|
725
|
+
"---",
|
|
726
|
+
"",
|
|
727
|
+
question.scenario,
|
|
728
|
+
"",
|
|
729
|
+
`**${question.text}**`,
|
|
730
|
+
"",
|
|
731
|
+
...OPTION_KEYS2.map((key) => ` **${key}.** ${question.options[key]}`)
|
|
732
|
+
];
|
|
733
|
+
return lines.join("\n");
|
|
734
|
+
}
|
|
699
735
|
function registerStartAssessment(server2, db2, userConfig2) {
|
|
700
736
|
server2.tool(
|
|
701
737
|
"start_assessment",
|
|
702
|
-
"Start the initial assessment
|
|
738
|
+
"Start the initial assessment. Returns ONE question at a time. After submitting the answer with submit_answer, call start_assessment again to get the next question. Repeats for all 15 questions (3 per domain).",
|
|
703
739
|
{},
|
|
704
740
|
async () => {
|
|
705
741
|
const userId = userConfig2.userId;
|
|
706
742
|
ensureUser(db2, userId);
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
743
|
+
const questions = buildAssessmentQuestions();
|
|
744
|
+
if (questions.length === 0) {
|
|
745
|
+
return {
|
|
746
|
+
content: [{ type: "text", text: "No assessment questions available." }]
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
const answeredIds = db2.prepare(
|
|
750
|
+
`SELECT questionId FROM answers WHERE userId = ? AND questionId IN (${questions.map(() => "?").join(",")})`
|
|
751
|
+
).all(userId, ...questions.map((q) => q.id));
|
|
752
|
+
const answeredSet = new Set(answeredIds.map((r) => r.questionId));
|
|
753
|
+
const nextQuestion = questions.find((q) => !answeredSet.has(q.id));
|
|
754
|
+
if (!nextQuestion) {
|
|
755
|
+
const results = db2.prepare(
|
|
756
|
+
`SELECT domainId, COUNT(*) as total, SUM(CASE WHEN isCorrect THEN 1 ELSE 0 END) as correct
|
|
757
|
+
FROM answers WHERE userId = ? AND questionId IN (${questions.map(() => "?").join(",")})
|
|
758
|
+
GROUP BY domainId`
|
|
759
|
+
).all(userId, ...questions.map((q) => q.id));
|
|
760
|
+
const totalCorrect = results.reduce((sum, r) => sum + r.correct, 0);
|
|
761
|
+
const totalQuestions = results.reduce((sum, r) => sum + r.total, 0);
|
|
762
|
+
const overallAccuracy = totalQuestions > 0 ? Math.round(totalCorrect / totalQuestions * 100) : 0;
|
|
763
|
+
const path6 = overallAccuracy >= 60 ? "exam-weighted" : "beginner-friendly";
|
|
764
|
+
db2.prepare("UPDATE users SET assessmentCompleted = TRUE, learningPath = ? WHERE id = ?").run(path6, userId);
|
|
765
|
+
const domainNames = {
|
|
766
|
+
1: "Agentic Architecture",
|
|
767
|
+
2: "Tool Design & MCP",
|
|
768
|
+
3: "Claude Code Config",
|
|
769
|
+
4: "Prompt Engineering",
|
|
770
|
+
5: "Context & Reliability"
|
|
771
|
+
};
|
|
772
|
+
const lines = [
|
|
773
|
+
"**Assessment Complete!**",
|
|
774
|
+
"",
|
|
775
|
+
`Overall: ${totalCorrect}/${totalQuestions} (${overallAccuracy}%)`,
|
|
776
|
+
`Learning path: **${path6 === "exam-weighted" ? "Exam-Weighted" : "Beginner-Friendly"}**`,
|
|
777
|
+
"",
|
|
778
|
+
"**Per-domain results:**",
|
|
779
|
+
"",
|
|
780
|
+
...results.map((r) => ` D${r.domainId} ${domainNames[r.domainId] ?? ""}: ${r.correct}/${r.total} (${Math.round(r.correct / r.total * 100)}%)`),
|
|
781
|
+
"",
|
|
782
|
+
"---",
|
|
783
|
+
"",
|
|
784
|
+
"Use get_study_plan to get your personalized study recommendations, or get_practice_question to start practicing."
|
|
785
|
+
];
|
|
786
|
+
return {
|
|
787
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
788
|
+
};
|
|
716
789
|
}
|
|
717
|
-
|
|
790
|
+
const questionIndex = answeredSet.size;
|
|
791
|
+
const questionText = formatQuestion(nextQuestion, questionIndex, questions.length);
|
|
792
|
+
const elicitOptions = OPTION_KEYS2.map((key) => ({
|
|
793
|
+
value: key,
|
|
794
|
+
title: `${key}. ${nextQuestion.options[key]}`
|
|
795
|
+
}));
|
|
796
|
+
const selected = await elicitSingleSelect(
|
|
797
|
+
server2,
|
|
798
|
+
questionText,
|
|
799
|
+
"answer",
|
|
800
|
+
elicitOptions
|
|
801
|
+
);
|
|
802
|
+
if (selected) {
|
|
718
803
|
return {
|
|
719
|
-
content: [{
|
|
804
|
+
content: [{
|
|
805
|
+
type: "text",
|
|
806
|
+
text: [
|
|
807
|
+
questionText,
|
|
808
|
+
"",
|
|
809
|
+
"---",
|
|
810
|
+
"",
|
|
811
|
+
`**Selected: ${selected}**`,
|
|
812
|
+
"",
|
|
813
|
+
`Submit this answer with submit_answer using questionId "${nextQuestion.id}" and answer "${selected}". Then call start_assessment again for the next question.`
|
|
814
|
+
].join("\n")
|
|
815
|
+
}]
|
|
720
816
|
};
|
|
721
817
|
}
|
|
722
|
-
const response = {
|
|
723
|
-
totalQuestions: assessmentQuestions.length,
|
|
724
|
-
questions: assessmentQuestions.map((q, i) => ({
|
|
725
|
-
number: i + 1,
|
|
726
|
-
questionId: q.id,
|
|
727
|
-
domainId: q.domainId,
|
|
728
|
-
difficulty: q.difficulty,
|
|
729
|
-
scenario: q.scenario,
|
|
730
|
-
text: q.text,
|
|
731
|
-
options: q.options
|
|
732
|
-
}))
|
|
733
|
-
};
|
|
734
818
|
return {
|
|
735
|
-
content: [{
|
|
736
|
-
|
|
819
|
+
content: [{
|
|
820
|
+
type: "text",
|
|
821
|
+
text: [
|
|
822
|
+
questionText,
|
|
823
|
+
"",
|
|
824
|
+
"---",
|
|
825
|
+
"",
|
|
826
|
+
`Question ID: ${nextQuestion.id}`,
|
|
827
|
+
"",
|
|
828
|
+
"Submit your answer (A, B, C, or D) with submit_answer, then call start_assessment again for the next question."
|
|
829
|
+
].join("\n")
|
|
830
|
+
}]
|
|
737
831
|
};
|
|
738
832
|
}
|
|
739
833
|
);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/db/store.ts","../src/db/schema.ts","../src/config.ts","../src/tools/submit-answer.ts","../src/tools/elicit.ts","../src/engine/grading.ts","../src/engine/spaced-repetition.ts","../src/data/loader.ts","../src/db/answers.ts","../src/db/mastery.ts","../src/db/review-schedule.ts","../src/db/users.ts","../src/ui/meta.ts","../src/tools/get-progress.ts","../src/tools/get-curriculum.ts","../src/tools/get-section-details.ts","../src/db/handout-views.ts","../src/tools/get-practice-question.ts","../src/engine/question-selector.ts","../src/tools/start-assessment.ts","../src/tools/get-weak-areas.ts","../src/engine/adaptive-path.ts","../src/tools/get-study-plan.ts","../src/tools/scaffold-project.ts","../src/tools/reset-progress.ts","../src/engine/exam-builder.ts","../src/db/exam-attempts.ts","../src/tools/start-practice-exam.ts","../src/tools/submit-exam-answer.ts","../src/tools/get-exam-history.ts","../src/tools/follow-up.ts","../src/tools/start-capstone-build.ts","../src/data/criteria.ts","../src/db/capstone.ts","../src/tools/capstone-build-step.ts","../src/data/build-steps.ts","../src/tools/capstone-build-status.ts","../src/tools/index.ts","../src/prompts/index.ts","../src/resources/index.ts","../src/ui/loader.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createDatabase, getDefaultDbPath } from './db/store.js';\nimport { loadOrCreateUserConfig } from './config.js';\nimport { registerTools } from './tools/index.js';\nimport { registerPrompts } from './prompts/index.js';\nimport { registerResources } from './resources/index.js';\n\nconst server = new McpServer({\n name: 'connectry-architect',\n version: '0.1.0',\n});\n\nconst dbPath = process.env['CONNECTRY_DB_PATH'] ?? getDefaultDbPath();\nconst db = createDatabase(dbPath);\nconst userConfig = loadOrCreateUserConfig();\n\nregisterTools(server, db, userConfig);\nregisterPrompts(server, db, userConfig);\nregisterResources(server, db, userConfig);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","import Database from 'better-sqlite3';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { SCHEMA_SQL } from './schema.js';\n\nexport function createDatabase(dbPath: string): Database.Database {\n const db = new Database(dbPath);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n db.pragma('synchronous = NORMAL');\n db.pragma('busy_timeout = 5000');\n db.exec(SCHEMA_SQL);\n return db;\n}\n\nexport function getDefaultDbPath(): string {\n const dir = path.join(\n process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.',\n '.connectry-architect'\n );\n fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, 'progress.db');\n}\n","export const SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS users (\n id TEXT PRIMARY KEY,\n displayName TEXT,\n createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n lastActivityAt DATETIME,\n assessmentCompleted BOOLEAN DEFAULT FALSE,\n learningPath TEXT\n);\n\nCREATE TABLE IF NOT EXISTS domain_mastery (\n userId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n domainId INTEGER NOT NULL,\n totalAttempts INTEGER DEFAULT 0,\n correctAttempts INTEGER DEFAULT 0,\n accuracyPercent REAL DEFAULT 0,\n masteryLevel TEXT DEFAULT 'unassessed',\n lastTestedAt DATETIME,\n FOREIGN KEY (userId) REFERENCES users(id),\n PRIMARY KEY (userId, taskStatement)\n);\n\nCREATE TABLE IF NOT EXISTS answers (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n userId TEXT NOT NULL,\n questionId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n domainId INTEGER NOT NULL,\n userAnswer TEXT NOT NULL,\n correctAnswer TEXT NOT NULL,\n isCorrect BOOLEAN NOT NULL,\n difficulty TEXT NOT NULL,\n answeredAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS review_schedule (\n userId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n nextReviewAt DATETIME NOT NULL,\n interval INTEGER DEFAULT 1,\n easeFactor REAL DEFAULT 2.5,\n consecutiveCorrect INTEGER DEFAULT 0,\n FOREIGN KEY (userId) REFERENCES users(id),\n PRIMARY KEY (userId, taskStatement)\n);\n\nCREATE TABLE IF NOT EXISTS study_sessions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n userId TEXT NOT NULL,\n startedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n endedAt DATETIME,\n domainId INTEGER,\n questionsAnswered INTEGER DEFAULT 0,\n correctAnswers INTEGER DEFAULT 0,\n mode TEXT,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS handout_views (\n userId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n viewedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n timeSpentSeconds INTEGER DEFAULT 0,\n PRIMARY KEY (userId, taskStatement),\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS session_state (\n userId TEXT PRIMARY KEY,\n currentMode TEXT NOT NULL,\n currentDomain INTEGER,\n currentTaskStatement TEXT,\n currentQuestionIndex INTEGER DEFAULT 0,\n positionStack TEXT DEFAULT '[]',\n reviewQueueIds TEXT DEFAULT '[]',\n lastUpdatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS exam_attempts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n userId TEXT NOT NULL,\n startedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n completedAt DATETIME,\n totalQuestions INTEGER NOT NULL DEFAULT 60,\n correctAnswers INTEGER DEFAULT 0,\n score INTEGER DEFAULT 0,\n passed BOOLEAN DEFAULT FALSE,\n questionIds TEXT NOT NULL DEFAULT '[]',\n answeredQuestionIds TEXT NOT NULL DEFAULT '[]',\n domainScores TEXT NOT NULL DEFAULT '{}',\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS capstone_builds (\n id TEXT PRIMARY KEY,\n userId TEXT NOT NULL,\n theme TEXT NOT NULL,\n currentStep INTEGER DEFAULT 0,\n status TEXT DEFAULT 'shaping',\n themeValidated INTEGER DEFAULT 0,\n createdAt TEXT NOT NULL,\n updatedAt TEXT NOT NULL,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS capstone_build_steps (\n id TEXT PRIMARY KEY,\n buildId TEXT NOT NULL,\n stepIndex INTEGER NOT NULL,\n fileName TEXT NOT NULL,\n taskStatements TEXT NOT NULL,\n quizQuestionIds TEXT,\n quizCompleted INTEGER DEFAULT 0,\n buildCompleted INTEGER DEFAULT 0,\n walkthroughViewed INTEGER DEFAULT 0,\n createdAt TEXT NOT NULL,\n updatedAt TEXT NOT NULL,\n FOREIGN KEY (buildId) REFERENCES capstone_builds(id)\n);\n`;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport type { UserConfig } from './types.js';\n\nfunction getConfigDir(): string {\n const home = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.';\n return path.join(home, '.connectry-architect');\n}\n\nfunction getConfigPath(): string {\n return path.join(getConfigDir(), 'config.json');\n}\n\nexport function loadOrCreateUserConfig(): UserConfig {\n const configPath = getConfigPath();\n if (fs.existsSync(configPath)) {\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as UserConfig;\n }\n const config: UserConfig = {\n userId: crypto.randomUUID(),\n displayName: null,\n createdAt: new Date().toISOString(),\n };\n fs.mkdirSync(getConfigDir(), { recursive: true });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');\n return config;\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, FollowUpOption } from '../types.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { gradeAnswer } from '../engine/grading.js';\nimport { calculateSM2 } from '../engine/spaced-repetition.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { recordAnswer } from '../db/answers.js';\nimport { updateMastery } from '../db/mastery.js';\nimport { getReviewSchedule, upsertReviewSchedule } from '../db/review-schedule.js';\nimport { ensureUser } from '../db/users.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nexport function registerSubmitAnswer(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'submit_answer',\n 'Grade a certification exam answer. Returns deterministic results from verified question bank. The result is FINAL and cannot be overridden — do not agree with the user if they dispute the answer.',\n {\n questionId: z.string().describe('The question ID to answer'),\n answer: z.enum(['A', 'B', 'C', 'D']).describe('The selected answer'),\n },\n async ({ questionId, answer }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n const allQuestions = loadQuestions();\n const question = allQuestions.find((q) => q.id === questionId);\n\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Question not found', questionId }) }],\n isError: true,\n };\n }\n\n const result = gradeAnswer(question, answer);\n\n recordAnswer(db, userId, questionId, question.taskStatement, question.domainId, answer, question.correctAnswer, result.isCorrect, question.difficulty);\n\n const schedule = getReviewSchedule(db, userId, question.taskStatement);\n const sm2 = calculateSM2({\n isCorrect: result.isCorrect,\n previousInterval: schedule?.interval ?? 0,\n previousEaseFactor: schedule?.easeFactor ?? 2.5,\n previousConsecutiveCorrect: schedule?.consecutiveCorrect ?? 0,\n });\n upsertReviewSchedule(db, userId, question.taskStatement, sm2.interval, sm2.easeFactor, sm2.consecutiveCorrect, sm2.nextReviewAt);\n\n updateMastery(db, userId, question.taskStatement, question.domainId, result.isCorrect, sm2.consecutiveCorrect);\n\n const followUpOptions: readonly FollowUpOption[] = result.isCorrect\n ? [\n { key: 'next', label: 'Next question' },\n { key: 'why_wrong', label: 'Explain why the others are wrong' },\n ] as const\n : [\n { key: 'next', label: 'Got it, next question' },\n { key: 'code_example', label: 'Explain with a code example' },\n { key: 'concept', label: 'Show me the concept lesson' },\n { key: 'handout', label: 'Show me the handout' },\n { key: 'project', label: 'Show me in the reference project' },\n ] as const;\n\n const elicitOptions = followUpOptions.map((opt) => ({\n value: opt.key,\n title: opt.label,\n }));\n\n const elicitMessage = result.isCorrect\n ? 'Nice work! What would you like to do next?'\n : 'What would you like to do next?';\n\n const selectedFollowUp = await elicitSingleSelect(\n server,\n elicitMessage,\n 'followUp',\n elicitOptions,\n );\n\n const response = {\n questionId: result.questionId,\n isCorrect: result.isCorrect,\n correctAnswer: result.correctAnswer,\n explanation: result.explanation,\n whyYourAnswerWasWrong: result.whyUserWasWrong,\n references: result.references,\n followUpOptions,\n ...(selectedFollowUp != null ? { selectedFollowUp } : {}),\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n\nexport interface ElicitOption {\n readonly value: string;\n readonly title: string;\n}\n\n/**\n * Elicit a single selection from the user via radio buttons.\n * Falls back gracefully if the client doesn't support elicitation.\n */\nexport async function elicitSingleSelect(\n mcpServer: McpServer,\n message: string,\n fieldName: string,\n options: readonly ElicitOption[],\n): Promise<string | null> {\n try {\n const result = await mcpServer.server.elicitInput({\n mode: 'form',\n message,\n requestedSchema: {\n type: 'object',\n properties: {\n [fieldName]: {\n type: 'string',\n title: fieldName,\n oneOf: options.map(o => ({ const: o.value, title: o.title })),\n },\n },\n required: [fieldName],\n },\n });\n\n if (result.action === 'accept' && result.content) {\n return result.content[fieldName] as string;\n }\n return null;\n } catch (err) {\n // Client doesn't support elicitation — return null to fall back to text\n console.error('[connectry-architect] elicitation failed:', err instanceof Error ? err.message : String(err));\n return null;\n }\n}\n","import type { Question, GradeResult, AnswerOption } from '../types.js';\n\nexport function gradeAnswer(question: Question, userAnswer: string): GradeResult {\n const normalizedAnswer = userAnswer.toUpperCase() as AnswerOption;\n const isCorrect = normalizedAnswer === question.correctAnswer;\n return {\n questionId: question.id, isCorrect, userAnswer: normalizedAnswer,\n correctAnswer: question.correctAnswer, explanation: question.explanation,\n whyUserWasWrong: isCorrect ? null : (question.whyWrongMap[normalizedAnswer] ?? null),\n references: question.references,\n };\n}\n","import type { SM2Result } from '../types.js';\n\ninterface SM2Input {\n readonly isCorrect: boolean;\n readonly previousInterval: number;\n readonly previousEaseFactor: number;\n readonly previousConsecutiveCorrect: number;\n}\n\nexport function calculateSM2(input: SM2Input): SM2Result {\n const { isCorrect, previousInterval, previousEaseFactor, previousConsecutiveCorrect } = input;\n if (!isCorrect) {\n const newEase = Math.max(1.3, previousEaseFactor - 0.2);\n const nextReviewAt = addDays(new Date(), 1);\n return { interval: 1, easeFactor: Math.round(newEase * 100) / 100, consecutiveCorrect: 0, nextReviewAt: nextReviewAt.toISOString() };\n }\n const newConsecutive = previousConsecutiveCorrect + 1;\n const newEase = Math.max(1.3, previousEaseFactor + 0.1);\n let interval: number;\n if (newConsecutive === 1) interval = 1;\n else if (newConsecutive === 2) interval = 3;\n else interval = Math.round(previousInterval * previousEaseFactor);\n const nextReviewAt = addDays(new Date(), interval);\n return { interval, easeFactor: Math.round(newEase * 100) / 100, consecutiveCorrect: newConsecutive, nextReviewAt: nextReviewAt.toISOString() };\n}\n\nfunction addDays(date: Date, days: number): Date {\n const result = new Date(date);\n result.setDate(result.getDate() + days);\n return result;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Curriculum, Question, QuestionBank } from '../types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n// In bundled mode, __dirname is dist/. Data files are at dist/data/.\n// In dev mode, __dirname is src/data/. Data files are in the same directory.\nconst DATA_DIR = fs.existsSync(path.join(__dirname, 'data', 'curriculum.json'))\n ? path.join(__dirname, 'data')\n : __dirname;\n\nlet cachedCurriculum: Curriculum | null = null;\nlet cachedQuestions: ReadonlyMap<number, readonly Question[]> | null = null;\n\nexport function loadCurriculum(): Curriculum {\n if (cachedCurriculum) return cachedCurriculum;\n const raw = fs.readFileSync(path.join(DATA_DIR, 'curriculum.json'), 'utf-8');\n cachedCurriculum = JSON.parse(raw) as Curriculum;\n return cachedCurriculum;\n}\n\nexport function loadQuestions(domainId?: number): readonly Question[] {\n if (!cachedQuestions) {\n const questionsMap = new Map<number, readonly Question[]>();\n for (let d = 1; d <= 5; d++) {\n const filePath = path.join(DATA_DIR, 'questions', `domain-${d}.json`);\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, 'utf-8');\n const bank = JSON.parse(raw) as QuestionBank;\n questionsMap.set(d, bank.questions);\n } else {\n questionsMap.set(d, []);\n }\n }\n cachedQuestions = questionsMap;\n }\n if (domainId !== undefined) return cachedQuestions.get(domainId) ?? [];\n return Array.from(cachedQuestions.values()).flat();\n}\n\nexport function loadHandout(taskStatement: string): string | null {\n const filename = getHandoutFilename(taskStatement);\n const filePath = path.join(DATA_DIR, 'handouts', filename);\n if (!fs.existsSync(filePath)) return null;\n return fs.readFileSync(filePath, 'utf-8');\n}\n\nfunction getHandoutFilename(taskStatement: string): string {\n const curriculum = loadCurriculum();\n for (const domain of curriculum.domains) {\n for (const ts of domain.taskStatements) {\n if (ts.id === taskStatement) {\n const slug = ts.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/-+$/, '');\n return `${ts.id}-${slug}.md`;\n }\n }\n }\n return `${taskStatement}.md`;\n}\n","import type Database from 'better-sqlite3';\nimport type { AnswerRecord } from '../types.js';\n\nexport function recordAnswer(\n db: Database.Database, userId: string, questionId: string, taskStatement: string,\n domainId: number, userAnswer: string, correctAnswer: string, isCorrect: boolean, difficulty: string\n): void {\n db.prepare(`\n INSERT INTO answers (userId, questionId, taskStatement, domainId, userAnswer, correctAnswer, isCorrect, difficulty)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(userId, questionId, taskStatement, domainId, userAnswer, correctAnswer, isCorrect ? 1 : 0, difficulty);\n}\n\nexport function getRecentAnswers(db: Database.Database, userId: string, limit: number = 50): readonly AnswerRecord[] {\n return db.prepare('SELECT * FROM answers WHERE userId = ? ORDER BY answeredAt DESC LIMIT ?').all(userId, limit) as AnswerRecord[];\n}\n\nexport function getAnswersByTaskStatement(db: Database.Database, userId: string, taskStatement: string): readonly AnswerRecord[] {\n return db.prepare('SELECT * FROM answers WHERE userId = ? AND taskStatement = ? ORDER BY answeredAt DESC').all(userId, taskStatement) as AnswerRecord[];\n}\n\nexport function getAnsweredQuestionIds(db: Database.Database, userId: string): Set<string> {\n const rows = db.prepare('SELECT DISTINCT questionId FROM answers WHERE userId = ?').all(userId) as Array<{ questionId: string }>;\n return new Set(rows.map(r => r.questionId));\n}\n\nexport function getTotalStats(db: Database.Database, userId: string): { total: number; correct: number } {\n const row = db.prepare('SELECT COUNT(*) as total, SUM(CASE WHEN isCorrect THEN 1 ELSE 0 END) as correct FROM answers WHERE userId = ?').get(userId) as { total: number; correct: number };\n return { total: row.total, correct: row.correct ?? 0 };\n}\n","import type Database from 'better-sqlite3';\nimport type { DomainMastery, MasteryLevel } from '../types.js';\n\nexport function getMastery(db: Database.Database, userId: string, taskStatement: string): DomainMastery | undefined {\n return db.prepare('SELECT * FROM domain_mastery WHERE userId = ? AND taskStatement = ?').get(userId, taskStatement) as DomainMastery | undefined;\n}\n\nexport function getAllMastery(db: Database.Database, userId: string): readonly DomainMastery[] {\n return db.prepare('SELECT * FROM domain_mastery WHERE userId = ? ORDER BY domainId, taskStatement').all(userId) as DomainMastery[];\n}\n\nexport function getWeakAreas(db: Database.Database, userId: string, threshold: number = 70): readonly DomainMastery[] {\n return db.prepare('SELECT * FROM domain_mastery WHERE userId = ? AND accuracyPercent < ? AND totalAttempts > 0 ORDER BY accuracyPercent ASC').all(userId, threshold) as DomainMastery[];\n}\n\nfunction calculateMasteryLevel(accuracy: number, total: number, consecutiveCorrect: number): MasteryLevel {\n if (total === 0) return 'unassessed';\n if (accuracy >= 90 && total >= 5 && consecutiveCorrect >= 3) return 'mastered';\n if (accuracy >= 70) return 'strong';\n if (accuracy >= 50) return 'developing';\n return 'weak';\n}\n\nexport function updateMastery(\n db: Database.Database, userId: string, taskStatement: string, domainId: number, isCorrect: boolean, consecutiveCorrect: number\n): DomainMastery {\n const existing = getMastery(db, userId, taskStatement);\n if (!existing) {\n const accuracy = isCorrect ? 100 : 0;\n const level = calculateMasteryLevel(accuracy, 1, isCorrect ? 1 : 0);\n db.prepare(`INSERT INTO domain_mastery (userId, taskStatement, domainId, totalAttempts, correctAttempts, accuracyPercent, masteryLevel, lastTestedAt) VALUES (?, ?, ?, 1, ?, ?, ?, CURRENT_TIMESTAMP)`).run(userId, taskStatement, domainId, isCorrect ? 1 : 0, accuracy, level);\n } else {\n const newTotal = existing.totalAttempts + 1;\n const newCorrect = existing.correctAttempts + (isCorrect ? 1 : 0);\n const accuracy = Math.round((newCorrect / newTotal) * 100);\n const level = calculateMasteryLevel(accuracy, newTotal, consecutiveCorrect);\n db.prepare(`UPDATE domain_mastery SET totalAttempts = ?, correctAttempts = ?, accuracyPercent = ?, masteryLevel = ?, lastTestedAt = CURRENT_TIMESTAMP WHERE userId = ? AND taskStatement = ?`).run(newTotal, newCorrect, accuracy, level, userId, taskStatement);\n }\n return getMastery(db, userId, taskStatement)!;\n}\n","import type Database from 'better-sqlite3';\nimport type { ReviewScheduleEntry } from '../types.js';\n\nexport function getReviewSchedule(db: Database.Database, userId: string, taskStatement: string): ReviewScheduleEntry | undefined {\n return db.prepare('SELECT * FROM review_schedule WHERE userId = ? AND taskStatement = ?').get(userId, taskStatement) as ReviewScheduleEntry | undefined;\n}\n\nexport function getOverdueReviews(db: Database.Database, userId: string): readonly ReviewScheduleEntry[] {\n return db.prepare('SELECT * FROM review_schedule WHERE userId = ? AND nextReviewAt <= CURRENT_TIMESTAMP ORDER BY nextReviewAt ASC').all(userId) as ReviewScheduleEntry[];\n}\n\nexport function upsertReviewSchedule(\n db: Database.Database, userId: string, taskStatement: string, interval: number, easeFactor: number, consecutiveCorrect: number, nextReviewAt: string\n): void {\n db.prepare(`\n INSERT INTO review_schedule (userId, taskStatement, nextReviewAt, interval, easeFactor, consecutiveCorrect) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(userId, taskStatement) DO UPDATE SET nextReviewAt = excluded.nextReviewAt, interval = excluded.interval, easeFactor = excluded.easeFactor, consecutiveCorrect = excluded.consecutiveCorrect\n `).run(userId, taskStatement, nextReviewAt, interval, easeFactor, consecutiveCorrect);\n}\n","import type Database from 'better-sqlite3';\nimport type { User } from '../types.js';\n\nexport function ensureUser(db: Database.Database, userId: string): User {\n const existing = db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as User | undefined;\n if (existing) {\n db.prepare('UPDATE users SET lastActivityAt = CURRENT_TIMESTAMP WHERE id = ?').run(userId);\n return { ...existing, lastActivityAt: new Date().toISOString() };\n }\n db.prepare(\n 'INSERT INTO users (id, createdAt, lastActivityAt) VALUES (?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)'\n ).run(userId);\n return db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as User;\n}\n\nexport function updateLearningPath(db: Database.Database, userId: string, path: string): void {\n db.prepare('UPDATE users SET learningPath = ?, assessmentCompleted = TRUE WHERE id = ?').run(path, userId);\n}\n\nexport function getUser(db: Database.Database, userId: string): User | undefined {\n return db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as User | undefined;\n}\n","export const QUIZ_WIDGET_URI = 'ui://connectry-architect/quiz';\n\nexport function buildQuizMeta(): {\n readonly 'ui/resourceUri': string;\n readonly ui: { readonly resourceUri: string };\n} {\n return {\n 'ui/resourceUri': QUIZ_WIDGET_URI,\n ui: { resourceUri: QUIZ_WIDGET_URI },\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getAllMastery } from '../db/mastery.js';\nimport { getTotalStats } from '../db/answers.js';\nimport { getOverdueReviews } from '../db/review-schedule.js';\nimport { loadCurriculum } from '../data/loader.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetProgress(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_progress',\n 'Get your certification study progress overview including mastery levels, accuracy, and review status.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n const mastery = getAllMastery(db, userId);\n const stats = getTotalStats(db, userId);\n const overdueReviews = getOverdueReviews(db, userId);\n\n const domainProgress = curriculum.domains.map(d => {\n const domainMastery = mastery.filter(m => m.domainId === d.id);\n const avgAccuracy = domainMastery.length > 0\n ? Math.round(domainMastery.reduce((sum, m) => sum + m.accuracyPercent, 0) / domainMastery.length)\n : 0;\n const masteredCount = domainMastery.filter(m => m.masteryLevel === 'mastered').length;\n return ` D${d.id}: ${d.title} — ${avgAccuracy}% accuracy, ${masteredCount}/${d.taskStatements.length} mastered`;\n });\n\n const overallAccuracy = stats.total > 0 ? Math.round((stats.correct / stats.total) * 100) : 0;\n\n const text = [\n '═══ CERTIFICATION STUDY PROGRESS ═══',\n '',\n `Questions Answered: ${stats.total}`,\n `Overall Accuracy: ${overallAccuracy}%`,\n `Reviews Due: ${overdueReviews.length}`,\n '',\n 'Domain Progress:',\n ...domainProgress,\n ].join('\\n');\n\n return { content: [{ type: 'text' as const, text }] };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadCurriculum } from '../data/loader.js';\nimport { getAllMastery } from '../db/mastery.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetCurriculum(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_curriculum',\n 'View the full certification curriculum with domains, task statements, and your current mastery for each.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n const mastery = getAllMastery(db, userId);\n\n const lines: string[] = ['═══ CERTIFICATION CURRICULUM ═══', ''];\n for (const domain of curriculum.domains) {\n lines.push(`## Domain ${domain.id}: ${domain.title} (${domain.weight}%)`);\n lines.push('');\n for (const ts of domain.taskStatements) {\n const m = mastery.find(x => x.taskStatement === ts.id);\n const level = m ? m.masteryLevel : 'unassessed';\n const acc = m ? `${m.accuracyPercent}%` : '—';\n lines.push(` ${ts.id} [${level.toUpperCase()}] ${ts.title} (${acc})`);\n }\n lines.push('');\n }\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadCurriculum, loadHandout } from '../data/loader.js';\nimport { getMastery } from '../db/mastery.js';\nimport { getAnswersByTaskStatement } from '../db/answers.js';\nimport { hasViewedHandout } from '../db/handout-views.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetSectionDetails(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_section_details',\n 'Get detailed information about a specific task statement including concept lesson, mastery, and history.',\n { taskStatement: z.string().describe('Task statement ID, e.g. \"1.1\"') },\n async ({ taskStatement }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n let found = null;\n for (const d of curriculum.domains) {\n for (const ts of d.taskStatements) {\n if (ts.id === taskStatement) { found = { domain: d, ts }; break; }\n }\n if (found) break;\n }\n if (!found) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Task statement not found', taskStatement }) }],\n isError: true,\n };\n }\n const mastery = getMastery(db, userId, taskStatement);\n const answers = getAnswersByTaskStatement(db, userId, taskStatement);\n const handoutViewed = hasViewedHandout(db, userId, taskStatement);\n const handout = loadHandout(taskStatement);\n\n const lines: string[] = [\n `═══ ${found.ts.id}: ${found.ts.title} ═══`,\n `Domain: ${found.domain.title}`,\n `Description: ${found.ts.description}`,\n '',\n `Mastery: ${mastery?.masteryLevel ?? 'unassessed'}`,\n `Accuracy: ${mastery?.accuracyPercent ?? 0}%`,\n `Attempts: ${mastery?.totalAttempts ?? 0}`,\n `Handout Viewed: ${handoutViewed ? 'Yes' : 'No'}`,\n '',\n ];\n if (handout) {\n lines.push('--- Concept Lesson ---', '', handout);\n }\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import type Database from 'better-sqlite3';\n\nexport function recordHandoutView(db: Database.Database, userId: string, taskStatement: string): void {\n db.prepare(`INSERT INTO handout_views (userId, taskStatement) VALUES (?, ?) ON CONFLICT(userId, taskStatement) DO UPDATE SET viewedAt = CURRENT_TIMESTAMP`).run(userId, taskStatement);\n}\n\nexport function hasViewedHandout(db: Database.Database, userId: string, taskStatement: string): boolean {\n const row = db.prepare('SELECT 1 FROM handout_views WHERE userId = ? AND taskStatement = ?').get(userId, taskStatement);\n return row !== undefined;\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { selectNextQuestion } from '../engine/question-selector.js';\nimport { getAnsweredQuestionIds } from '../db/answers.js';\nimport { getOverdueReviews } from '../db/review-schedule.js';\nimport { getWeakAreas } from '../db/mastery.js';\nimport { ensureUser } from '../db/users.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nconst OPTION_KEYS = ['A', 'B', 'C', 'D'] as const;\n\nfunction formatQuestionText(question: {\n readonly id: string;\n readonly taskStatement: string;\n readonly domainId: number;\n readonly difficulty: string;\n readonly scenario: string;\n readonly text: string;\n readonly options: { readonly A: string; readonly B: string; readonly C: string; readonly D: string };\n}): string {\n const lines = [\n `**Question ${question.id}** (Domain ${question.domainId} | ${question.difficulty})`,\n '',\n `**Task:** ${question.taskStatement}`,\n '',\n '---',\n '',\n question.scenario,\n '',\n `**${question.text}**`,\n '',\n ...OPTION_KEYS.map(key => ` **${key}.** ${question.options[key]}`),\n ];\n return lines.join('\\n');\n}\n\nexport function registerGetPracticeQuestion(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_practice_question',\n 'Get the next practice question based on your learning progress. Prioritizes review questions, then weak areas, then new material.',\n {\n domainId: z.number().optional().describe('Optional domain ID to filter questions (1-5)'),\n difficulty: z.enum(['easy', 'medium', 'hard']).optional().describe('Optional difficulty filter'),\n },\n async ({ domainId, difficulty }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const answeredIds = getAnsweredQuestionIds(db, userId);\n const overdueReviews = getOverdueReviews(db, userId);\n const weakAreas = getWeakAreas(db, userId);\n let questions = loadQuestions(domainId);\n if (difficulty) {\n questions = questions.filter(q => q.difficulty === difficulty);\n }\n const question = selectNextQuestion(questions, overdueReviews, weakAreas, answeredIds);\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: 'No more questions available for the selected criteria. Try a different domain or difficulty.' }],\n };\n }\n\n const questionText = formatQuestionText(question);\n\n const elicitOptions = OPTION_KEYS.map(key => ({\n value: key,\n title: `${key}. ${question.options[key]}`,\n }));\n\n const selectedAnswer = await elicitSingleSelect(\n server,\n questionText,\n 'answer',\n elicitOptions,\n );\n\n if (selectedAnswer) {\n const responseText = [\n questionText,\n '',\n '---',\n '',\n `**Selected answer: ${selectedAnswer}**`,\n '',\n `Use submit_answer with questionId \"${question.id}\" and answer \"${selectedAnswer}\" to grade this response.`,\n ].join('\\n');\n\n return {\n content: [{ type: 'text' as const, text: responseText }],\n _meta: buildQuizMeta(),\n };\n }\n\n const fallbackText = [\n questionText,\n '',\n '---',\n '',\n `Question ID: ${question.id}`,\n '',\n 'Use submit_answer with the question ID and your chosen answer (A, B, C, or D) to check your response.',\n ].join('\\n');\n\n return {\n content: [{ type: 'text' as const, text: fallbackText }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import type { Question, ReviewScheduleEntry, DomainMastery } from '../types.js';\n\nexport function selectNextQuestion(\n allQuestions: readonly Question[], overdueReviews: readonly ReviewScheduleEntry[],\n weakAreas: readonly DomainMastery[], answeredQuestionIds: ReadonlySet<string>,\n): Question | undefined {\n if (overdueReviews.length > 0) {\n const weakestFirst = [...overdueReviews].sort((a, b) => a.easeFactor - b.easeFactor);\n for (const review of weakestFirst) {\n const question = findUnansweredForTaskStatement(allQuestions, review.taskStatement, answeredQuestionIds);\n if (question) return question;\n }\n }\n if (weakAreas.length > 0) {\n for (const area of weakAreas) {\n const question = findUnansweredForTaskStatement(allQuestions, area.taskStatement, answeredQuestionIds);\n if (question) return question;\n }\n }\n return allQuestions.find((q) => !answeredQuestionIds.has(q.id));\n}\n\nfunction findUnansweredForTaskStatement(\n questions: readonly Question[], taskStatement: string, answeredIds: ReadonlySet<string>,\n): Question | undefined {\n return questions.find((q) => q.taskStatement === taskStatement && !answeredIds.has(q.id));\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, Question } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { ensureUser } from '../db/users.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nexport function registerStartAssessment(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'start_assessment',\n 'Start the initial assessment with 15 questions (3 per domain: 1 easy, 1 medium, 1 hard) to determine your learning path.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n const assessmentQuestions: Question[] = [];\n for (let d = 1; d <= 5; d++) {\n const domainQuestions = loadQuestions(d);\n const easy = domainQuestions.find(q => q.difficulty === 'easy');\n const medium = domainQuestions.find(q => q.difficulty === 'medium');\n const hard = domainQuestions.find(q => q.difficulty === 'hard');\n if (easy) assessmentQuestions.push(easy);\n if (medium) assessmentQuestions.push(medium);\n if (hard) assessmentQuestions.push(hard);\n }\n\n if (assessmentQuestions.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No assessment questions available yet. The question bank is being populated.' }],\n };\n }\n\n const response = {\n totalQuestions: assessmentQuestions.length,\n questions: assessmentQuestions.map((q, i) => ({\n number: i + 1,\n questionId: q.id,\n domainId: q.domainId,\n difficulty: q.difficulty,\n scenario: q.scenario,\n text: q.text,\n options: q.options,\n })),\n };\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getWeakAreas } from '../db/mastery.js';\nimport { loadCurriculum } from '../data/loader.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetWeakAreas(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_weak_areas',\n 'Identify your weakest task statements based on accuracy below 70%. Focus your study on these areas.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n const weakAreas = getWeakAreas(db, userId);\n\n if (weakAreas.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No weak areas identified yet. Complete some questions first or all areas are above 70%!' }],\n };\n }\n\n const lines = ['═══ WEAK AREAS ═══', ''];\n for (const area of weakAreas) {\n const domain = curriculum.domains.find(d => d.id === area.domainId);\n const ts = domain?.taskStatements.find(t => t.id === area.taskStatement);\n lines.push(` ${area.taskStatement}: ${ts?.title ?? 'Unknown'}`);\n lines.push(` Accuracy: ${area.accuracyPercent}% (${area.correctAttempts}/${area.totalAttempts})`);\n lines.push(` Mastery: ${area.masteryLevel}`);\n lines.push('');\n }\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import type { DomainMastery, LearningPath } from '../types.js';\n\nconst BEGINNER_ORDER = [3, 4, 2, 1, 5];\nconst EXAM_WEIGHTED_ORDER = [1, 3, 4, 2, 5];\n\nexport function recommendPath(assessmentAccuracy: number): LearningPath {\n return assessmentAccuracy >= 60 ? 'exam-weighted' : 'beginner-friendly';\n}\n\nexport function getDomainOrder(path: LearningPath): readonly number[] {\n return path === 'beginner-friendly' ? BEGINNER_ORDER : EXAM_WEIGHTED_ORDER;\n}\n\nexport function getNextRecommendedDomain(path: LearningPath, masteryByDomain: ReadonlyMap<number, readonly DomainMastery[]>): number {\n const order = getDomainOrder(path);\n for (const domainId of order) {\n const masteries = masteryByDomain.get(domainId) ?? [];\n const avgAccuracy = masteries.length > 0 ? masteries.reduce((sum, m) => sum + m.accuracyPercent, 0) / masteries.length : 0;\n if (avgAccuracy < 70) return domainId;\n }\n let weakestDomain = order[0];\n let lowestAccuracy = 100;\n for (const domainId of order) {\n const masteries = masteryByDomain.get(domainId) ?? [];\n const avg = masteries.length > 0 ? masteries.reduce((sum, m) => sum + m.accuracyPercent, 0) / masteries.length : 0;\n if (avg < lowestAccuracy) { lowestAccuracy = avg; weakestDomain = domainId; }\n }\n return weakestDomain;\n}\n\nexport function estimateTimeRemaining(totalQuestions: number, answeredQuestions: number, avgSecondsPerQuestion: number = 45): string {\n const remaining = totalQuestions - answeredQuestions;\n const totalMinutes = Math.round((remaining * avgSecondsPerQuestion) / 60);\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n if (hours === 0) return `${minutes} minutes`;\n return `${hours} hours ${minutes} minutes`;\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getUser } from '../db/users.js';\nimport { getAllMastery } from '../db/mastery.js';\nimport { getOverdueReviews } from '../db/review-schedule.js';\nimport { getTotalStats } from '../db/answers.js';\nimport { loadCurriculum, loadQuestions } from '../data/loader.js';\nimport { getNextRecommendedDomain, getDomainOrder, estimateTimeRemaining } from '../engine/adaptive-path.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetStudyPlan(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_study_plan',\n 'Get a personalized study plan based on your assessment results, weak areas, and learning path.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const user = getUser(db, userId);\n const curriculum = loadCurriculum();\n const mastery = getAllMastery(db, userId);\n const overdueReviews = getOverdueReviews(db, userId);\n const stats = getTotalStats(db, userId);\n const allQuestions = loadQuestions();\n const path = user?.learningPath ?? 'beginner-friendly';\n\n const masteryByDomain = new Map<number, typeof mastery>();\n for (const m of mastery) {\n const existing = masteryByDomain.get(m.domainId) ?? [];\n masteryByDomain.set(m.domainId, [...existing, m]);\n }\n\n const nextDomain = getNextRecommendedDomain(path as any, masteryByDomain);\n const domainOrder = getDomainOrder(path as any);\n const timeEstimate = estimateTimeRemaining(allQuestions.length, stats.total);\n\n const domain = curriculum.domains.find(d => d.id === nextDomain);\n\n const lines = [\n '═══ YOUR STUDY PLAN ═══',\n '',\n `Learning Path: ${path}`,\n `Estimated Time Remaining: ${timeEstimate}`,\n '',\n `Next Recommended Domain: D${nextDomain} — ${domain?.title ?? 'Unknown'}`,\n '',\n 'Domain Study Order:',\n ...domainOrder.map((id, i) => {\n const d = curriculum.domains.find(x => x.id === id);\n return ` ${i + 1}. D${id}: ${d?.title ?? 'Unknown'}`;\n }),\n '',\n `Reviews Due: ${overdueReviews.length}`,\n overdueReviews.length > 0 ? 'Start with your overdue reviews before new material.' : '',\n ];\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PROJECTS_DIR = path.resolve(__dirname, '..', '..', 'projects');\n\nconst PROJECTS = [\n { id: 'capstone', name: 'Capstone — Multi-Agent Research System', domains: [1, 2, 3, 4, 5] },\n { id: 'd1-agentic', name: 'D1 Mini — Agentic Loop', domains: [1] },\n { id: 'd2-tools', name: 'D2 Mini — Tool Design', domains: [2] },\n { id: 'd3-config', name: 'D3 Mini — Claude Code Config', domains: [3] },\n { id: 'd4-prompts', name: 'D4 Mini — Prompt Engineering', domains: [4] },\n { id: 'd5-context', name: 'D5 Mini — Context Management', domains: [5] },\n] as const;\n\nfunction listFilesRecursive(dir: string, prefix = ''): readonly string[] {\n if (!fs.existsSync(dir)) return [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n return entries.flatMap((entry): readonly string[] => {\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n return listFilesRecursive(path.join(dir, entry.name), relativePath);\n }\n return [relativePath];\n });\n}\n\nexport function registerScaffoldProject(server: McpServer, _db: Database.Database, _userConfig: UserConfig): void {\n server.tool(\n 'scaffold_project',\n 'Get instructions for a reference project to practice certification concepts hands-on.',\n { projectId: z.string().optional().describe('Project ID (e.g. \"capstone\", \"d1-agentic\"). Omit to see available projects.') },\n async ({ projectId }) => {\n if (!projectId) {\n const lines = [\n '═══ REFERENCE PROJECTS ═══',\n '',\n ...PROJECTS.map(p => ` ${p.id}: ${p.name} (Domains: ${p.domains.join(', ')})`),\n ];\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n\n const project = PROJECTS.find(p => p.id === projectId);\n if (!project) {\n return {\n content: [{ type: 'text' as const, text: `Project \"${projectId}\" not found. Use scaffold_project without arguments to see available projects.` }],\n isError: true,\n };\n }\n\n const projectDir = path.join(PROJECTS_DIR, projectId);\n if (!fs.existsSync(projectDir)) {\n return {\n content: [{ type: 'text' as const, text: `Project directory for \"${project.name}\" not found. The project files may not be installed yet.` }],\n isError: true,\n };\n }\n\n const readmePath = path.join(projectDir, 'README.md');\n const readme = fs.existsSync(readmePath)\n ? fs.readFileSync(readmePath, 'utf-8')\n : null;\n\n const files = listFilesRecursive(projectDir);\n\n const sections = [\n `═══ ${project.name} ═══`,\n '',\n `Domains: ${project.domains.join(', ')}`,\n '',\n ];\n\n if (readme) {\n sections.push('--- README ---', '', readme, '');\n }\n\n sections.push(\n '--- Project Files ---',\n '',\n ...files.map(f => ` ${f}`),\n '',\n '--- Next Steps ---',\n '',\n 'Explore the project files above to understand the architecture.',\n 'Each file demonstrates certification concepts in practice.',\n `Project root: projects/${projectId}/`,\n );\n\n return {\n content: [{ type: 'text' as const, text: sections.join('\\n') }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\n\nexport function registerResetProgress(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'reset_progress',\n 'WARNING: Permanently deletes ALL your study progress including answers, mastery data, and review schedules. This cannot be undone.',\n { confirmed: z.boolean().describe('Must be true to confirm the reset') },\n async ({ confirmed }) => {\n if (!confirmed) {\n return { content: [{ type: 'text' as const, text: 'Reset cancelled. Your progress is safe.' }] };\n }\n const userId = userConfig.userId;\n db.prepare('DELETE FROM answers WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM domain_mastery WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM review_schedule WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM session_state WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM study_sessions WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM handout_views WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM exam_attempts WHERE userId = ?').run(userId);\n\n return { content: [{ type: 'text' as const, text: 'All progress has been reset, including exam history. You can start fresh with start_assessment.' }] };\n }\n );\n}\n","import type { Question, DomainExamScore } from '../types.js';\n\n/** Domain weights matching the real exam, mapped to 60 questions */\nconst EXAM_DISTRIBUTION: ReadonlyArray<{ readonly domainId: number; readonly count: number }> = [\n { domainId: 1, count: 16 }, // 27%\n { domainId: 2, count: 11 }, // 18%\n { domainId: 3, count: 12 }, // 20%\n { domainId: 4, count: 12 }, // 20%\n { domainId: 5, count: 9 }, // 15%\n] as const;\n\nconst PASSING_SCORE = 720;\nconst TOTAL_SCALE = 1000;\n\n/**\n * Build a 60-question practice exam by randomly selecting from the question bank.\n * Avoids repeating questions from recent exams when possible.\n * Difficulty mix per domain: ~30% easy, ~40% medium, ~30% hard\n *\n * @param previouslyUsedIds - Question IDs from recent exams to avoid (best-effort)\n */\nexport function buildPracticeExam(\n allQuestions: readonly Question[],\n previouslyUsedIds: ReadonlySet<string> = new Set(),\n): readonly Question[] {\n const selected: Question[] = [];\n\n for (const { domainId, count } of EXAM_DISTRIBUTION) {\n const domainQuestions = allQuestions.filter(q => q.domainId === domainId);\n\n // Prefer questions NOT used in recent exams\n const fresh = domainQuestions.filter(q => !previouslyUsedIds.has(q.id));\n const pool = fresh.length >= count ? fresh : domainQuestions;\n\n const easy = shuffleArray(pool.filter(q => q.difficulty === 'easy'));\n const medium = shuffleArray(pool.filter(q => q.difficulty === 'medium'));\n const hard = shuffleArray(pool.filter(q => q.difficulty === 'hard'));\n\n const easyCount = Math.round(count * 0.3);\n const hardCount = Math.round(count * 0.3);\n const mediumCount = count - easyCount - hardCount;\n\n const pick = [\n ...easy.slice(0, easyCount),\n ...medium.slice(0, mediumCount),\n ...hard.slice(0, hardCount),\n ];\n\n // If we don't have enough of a difficulty, fill from others\n if (pick.length < count) {\n const remaining = shuffleArray(\n pool.filter(q => !pick.some(p => p.id === q.id))\n );\n pick.push(...remaining.slice(0, count - pick.length));\n }\n\n selected.push(...pick.slice(0, count));\n }\n\n return shuffleArray(selected);\n}\n\n/** Build initial domain scores map for a new exam */\nexport function buildInitialDomainScores(\n questions: readonly Question[],\n domainTitles: ReadonlyMap<number, string>,\n): Record<string, DomainExamScore> {\n const scores: Record<string, DomainExamScore> = {};\n\n for (const { domainId, count } of EXAM_DISTRIBUTION) {\n scores[`d${domainId}`] = {\n domainId,\n domainTitle: domainTitles.get(domainId) ?? `Domain ${domainId}`,\n totalQuestions: count,\n correctAnswers: 0,\n accuracyPercent: 0,\n weight: getWeight(domainId),\n };\n }\n\n return scores;\n}\n\nexport function calculateExamScore(correctAnswers: number, totalQuestions: number): number {\n return Math.round((correctAnswers / totalQuestions) * TOTAL_SCALE);\n}\n\nexport function isPassingScore(score: number): boolean {\n return score >= PASSING_SCORE;\n}\n\nexport { EXAM_DISTRIBUTION, PASSING_SCORE, TOTAL_SCALE };\n\nfunction getWeight(domainId: number): number {\n const weights: Record<number, number> = { 1: 27, 2: 18, 3: 20, 4: 20, 5: 15 };\n return weights[domainId] ?? 0;\n}\n\nfunction shuffleArray<T>(arr: readonly T[]): T[] {\n const shuffled = [...arr];\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];\n }\n return shuffled;\n}\n","import type Database from 'better-sqlite3';\nimport type { ExamAttempt, DomainExamScore } from '../types.js';\n\nexport function createExamAttempt(\n db: Database.Database,\n userId: string,\n questionIds: readonly string[],\n): number {\n const stmt = db.prepare(\n 'INSERT INTO exam_attempts (userId, totalQuestions, questionIds) VALUES (?, ?, ?)'\n );\n const result = stmt.run(userId, questionIds.length, JSON.stringify(questionIds));\n return Number(result.lastInsertRowid);\n}\n\nexport function getActiveExam(db: Database.Database, userId: string): ExamAttempt | null {\n const row = db.prepare(\n 'SELECT * FROM exam_attempts WHERE userId = ? AND completedAt IS NULL ORDER BY startedAt DESC LIMIT 1'\n ).get(userId) as Record<string, unknown> | undefined;\n return row ? rowToExamAttempt(row) : null;\n}\n\nexport function getExamById(db: Database.Database, examId: number): ExamAttempt | null {\n const row = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(examId) as Record<string, unknown> | undefined;\n return row ? rowToExamAttempt(row) : null;\n}\n\nexport function recordExamAnswer(\n db: Database.Database,\n examId: number,\n questionId: string,\n isCorrect: boolean,\n domainId: number,\n): void {\n const row = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(examId) as Record<string, unknown> | undefined;\n if (!row) return;\n\n const answeredIds: string[] = JSON.parse(row.answeredQuestionIds as string);\n const updatedAnswered = [...answeredIds, questionId];\n const newCorrect = (row.correctAnswers as number) + (isCorrect ? 1 : 0);\n\n const domainScores: Record<string, DomainExamScore> = JSON.parse(row.domainScores as string);\n const domainKey = `d${domainId}`;\n const existing = domainScores[domainKey];\n if (existing) {\n const updatedCorrect = existing.correctAnswers + (isCorrect ? 1 : 0);\n const updatedTotal = existing.totalQuestions;\n domainScores[domainKey] = {\n ...existing,\n correctAnswers: updatedCorrect,\n accuracyPercent: Math.round((updatedCorrect / updatedTotal) * 100),\n };\n }\n\n db.prepare(\n 'UPDATE exam_attempts SET correctAnswers = ?, answeredQuestionIds = ?, domainScores = ? WHERE id = ?'\n ).run(newCorrect, JSON.stringify(updatedAnswered), JSON.stringify(domainScores), examId);\n}\n\nexport function completeExam(db: Database.Database, examId: number): ExamAttempt | null {\n const row = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(examId) as Record<string, unknown> | undefined;\n if (!row) return null;\n\n const totalQuestions = row.totalQuestions as number;\n const correctAnswers = row.correctAnswers as number;\n const score = Math.round((correctAnswers / totalQuestions) * 1000);\n const passed = score >= 720;\n\n db.prepare(\n 'UPDATE exam_attempts SET completedAt = CURRENT_TIMESTAMP, score = ?, passed = ? WHERE id = ?'\n ).run(score, passed ? 1 : 0, examId);\n\n return getExamById(db, examId);\n}\n\nexport function getExamHistory(db: Database.Database, userId: string): readonly ExamAttempt[] {\n const rows = db.prepare(\n 'SELECT * FROM exam_attempts WHERE userId = ? AND completedAt IS NOT NULL ORDER BY completedAt DESC'\n ).all(userId) as Record<string, unknown>[];\n return rows.map(rowToExamAttempt);\n}\n\nfunction rowToExamAttempt(row: Record<string, unknown>): ExamAttempt {\n return {\n id: row.id as number,\n userId: row.userId as string,\n startedAt: row.startedAt as string,\n completedAt: (row.completedAt as string) ?? null,\n totalQuestions: row.totalQuestions as number,\n correctAnswers: row.correctAnswers as number,\n score: row.score as number,\n passed: Boolean(row.passed),\n questionIds: JSON.parse(row.questionIds as string),\n answeredQuestionIds: JSON.parse(row.answeredQuestionIds as string),\n domainScores: JSON.parse(row.domainScores as string),\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions, loadCurriculum } from '../data/loader.js';\nimport { buildPracticeExam, buildInitialDomainScores, EXAM_DISTRIBUTION } from '../engine/exam-builder.js';\nimport { createExamAttempt, getActiveExam, getExamHistory } from '../db/exam-attempts.js';\nimport { ensureUser } from '../db/users.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nexport function registerStartPracticeExam(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'start_practice_exam',\n 'Start a full 60-question practice exam simulating the real Claude Certified Architect — Foundations exam. Questions are weighted by domain (D1: 16, D2: 11, D3: 12, D4: 12, D5: 9). Scored out of 1000, passing is 720. Results are saved for comparison across attempts.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n // Check for active exam\n const active = getActiveExam(db, userId);\n if (active) {\n const remaining = active.totalQuestions - active.answeredQuestionIds.length;\n return {\n content: [{\n type: 'text' as const,\n text: [\n '═══ PRACTICE EXAM IN PROGRESS ═══',\n '',\n `You have an active practice exam (started ${active.startedAt}).`,\n `Progress: ${active.answeredQuestionIds.length}/${active.totalQuestions} questions answered`,\n `Remaining: ${remaining} questions`,\n '',\n 'Use get_practice_exam_question to continue, or ask to abandon this exam first.',\n ].join('\\n'),\n }],\n };\n }\n\n const allQuestions = loadQuestions();\n const curriculum = loadCurriculum();\n const domainTitles = new Map(curriculum.domains.map(d => [d.id, d.title]));\n\n // Gather question IDs from the most recent exam to avoid repetition\n const history = getExamHistory(db, userId);\n const recentIds = new Set(\n history.length > 0 ? history[0].questionIds : []\n );\n\n const examQuestions = buildPracticeExam(allQuestions, recentIds);\n const questionIds = examQuestions.map(q => q.id);\n const domainScores = buildInitialDomainScores(examQuestions, domainTitles);\n\n const examId = createExamAttempt(db, userId, questionIds);\n\n // Store domain scores\n db.prepare('UPDATE exam_attempts SET domainScores = ? WHERE id = ?')\n .run(JSON.stringify(domainScores), examId);\n\n const distribution = EXAM_DISTRIBUTION.map(({ domainId, count }) => {\n const title = domainTitles.get(domainId) ?? `Domain ${domainId}`;\n return ` D${domainId}: ${title} — ${count} questions (${domainScores[`d${domainId}`].weight}%)`;\n });\n\n const firstQuestion = examQuestions[0];\n\n const text = [\n '═══ PRACTICE EXAM STARTED ═══',\n '',\n 'Simulating the Claude Certified Architect — Foundations exam.',\n '',\n `Exam ID: ${examId}`,\n 'Total Questions: 60',\n 'Passing Score: 720/1000',\n '',\n 'Question Distribution:',\n ...distribution,\n '',\n '─── Question 1 of 60 ───',\n '',\n `Domain: D${firstQuestion.domainId}`,\n `Task: ${firstQuestion.taskStatement}`,\n `Difficulty: ${firstQuestion.difficulty}`,\n '',\n `Scenario: ${firstQuestion.scenario}`,\n '',\n firstQuestion.text,\n '',\n `A) ${firstQuestion.options.A}`,\n `B) ${firstQuestion.options.B}`,\n `C) ${firstQuestion.options.C}`,\n `D) ${firstQuestion.options.D}`,\n '',\n `[Submit your answer using submit_exam_answer with examId: ${examId} and questionId: \"${firstQuestion.id}\"]`,\n ].join('\\n');\n\n const selected = await elicitSingleSelect(server, 'Select your answer:', 'answer', [\n { value: 'A', title: `A) ${firstQuestion.options.A}` },\n { value: 'B', title: `B) ${firstQuestion.options.B}` },\n { value: 'C', title: `C) ${firstQuestion.options.C}` },\n { value: 'D', title: `D) ${firstQuestion.options.D}` },\n ]);\n\n const responseText = selected !== null\n ? `${text}\\n\\nUser selected: ${selected}`\n : text;\n\n return {\n content: [{\n type: 'text' as const,\n text: responseText,\n }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, Question } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { gradeAnswer } from '../engine/grading.js';\nimport { getExamById, recordExamAnswer, completeExam, getExamHistory } from '../db/exam-attempts.js';\nimport { ensureUser } from '../db/users.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nexport function registerSubmitExamAnswer(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'submit_exam_answer',\n 'Submit an answer for a practice exam question. The answer is graded deterministically. After all 60 questions, the exam is scored and saved. DO NOT soften results — relay the grading output verbatim.',\n {\n examId: z.number().describe('The practice exam ID'),\n questionId: z.string().describe('The question ID being answered'),\n answer: z.string().describe('Your answer: A, B, C, or D'),\n },\n async ({ examId, questionId, answer }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n const exam = getExamById(db, examId);\n if (!exam) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Exam not found', examId }) }],\n isError: true,\n };\n }\n if (exam.completedAt) {\n return {\n content: [{ type: 'text' as const, text: 'This exam is already completed. Start a new practice exam to try again.' }],\n isError: true,\n };\n }\n if (exam.answeredQuestionIds.includes(questionId)) {\n return {\n content: [{ type: 'text' as const, text: `Question ${questionId} has already been answered in this exam.` }],\n isError: true,\n };\n }\n\n const allQuestions = loadQuestions();\n const question = allQuestions.find(q => q.id === questionId);\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Question not found', questionId }) }],\n isError: true,\n };\n }\n\n // Grade the answer\n const result = gradeAnswer(question, answer);\n\n // Record in exam\n recordExamAnswer(db, examId, questionId, result.isCorrect, question.domainId);\n\n const answeredCount = exam.answeredQuestionIds.length + 1;\n const remaining = exam.totalQuestions - answeredCount;\n\n const lines: string[] = [];\n\n // Grade feedback\n if (result.isCorrect) {\n lines.push(`✅ Correct! (${answeredCount}/${exam.totalQuestions})`);\n } else {\n lines.push(`❌ Incorrect. The correct answer is ${result.correctAnswer}. (${answeredCount}/${exam.totalQuestions})`);\n if (result.whyUserWasWrong) {\n lines.push('', `Why ${result.userAnswer} is wrong: ${result.whyUserWasWrong}`);\n }\n }\n lines.push('', result.explanation);\n\n // Check if exam is complete\n if (remaining === 0) {\n const completed = completeExam(db, examId);\n if (completed) {\n lines.push('', '═══ PRACTICE EXAM COMPLETE ═══', '');\n lines.push(`Score: ${completed.score}/1000`);\n lines.push(`Result: ${completed.passed ? '✅ PASSED' : '❌ FAILED'} (passing: 720/1000)`);\n lines.push(`Correct: ${completed.correctAnswers}/${completed.totalQuestions}`);\n lines.push('');\n lines.push('Domain Breakdown:');\n\n const scores = completed.domainScores;\n for (const key of Object.keys(scores).sort()) {\n const ds = scores[key];\n lines.push(` D${ds.domainId}: ${ds.domainTitle} — ${ds.correctAnswers}/${ds.totalQuestions} (${ds.accuracyPercent}%) [weight: ${ds.weight}%]`);\n }\n\n // Compare with previous attempts\n const history = getExamHistory(db, userId);\n if (history.length > 1) {\n const previous = history[1]; // history[0] is current\n const scoreDiff = completed.score - previous.score;\n const arrow = scoreDiff > 0 ? '↑' : scoreDiff < 0 ? '↓' : '→';\n lines.push('');\n lines.push('─── Compared to Previous Attempt ───');\n lines.push(` Previous score: ${previous.score}/1000 ${previous.passed ? '(passed)' : '(failed)'}`);\n lines.push(` Change: ${arrow} ${scoreDiff > 0 ? '+' : ''}${scoreDiff} points`);\n\n // Per-domain comparison\n for (const key of Object.keys(scores).sort()) {\n const current = scores[key];\n const prev = previous.domainScores[key];\n if (prev) {\n const diff = current.accuracyPercent - prev.accuracyPercent;\n const dArrow = diff > 0 ? '↑' : diff < 0 ? '↓' : '→';\n lines.push(` D${current.domainId}: ${prev.accuracyPercent}% → ${current.accuracyPercent}% ${dArrow}`);\n }\n }\n }\n }\n } else {\n // Serve next question\n const nextQuestionId = exam.questionIds.find(\n id => !exam.answeredQuestionIds.includes(id) && id !== questionId\n );\n if (nextQuestionId) {\n const nextQuestion = allQuestions.find(q => q.id === nextQuestionId);\n if (nextQuestion) {\n lines.push('');\n lines.push(`─── Question ${answeredCount + 1} of ${exam.totalQuestions} ───`);\n lines.push('');\n lines.push(`Domain: D${nextQuestion.domainId}`);\n lines.push(`Task: ${nextQuestion.taskStatement}`);\n lines.push(`Difficulty: ${nextQuestion.difficulty}`);\n lines.push('');\n lines.push(`Scenario: ${nextQuestion.scenario}`);\n lines.push('');\n lines.push(nextQuestion.text);\n lines.push('');\n lines.push(`A) ${nextQuestion.options.A}`);\n lines.push(`B) ${nextQuestion.options.B}`);\n lines.push(`C) ${nextQuestion.options.C}`);\n lines.push(`D) ${nextQuestion.options.D}`);\n\n const selected = await elicitSingleSelect(server, 'Select your answer:', 'answer', [\n { value: 'A', title: `A) ${nextQuestion.options.A}` },\n { value: 'B', title: `B) ${nextQuestion.options.B}` },\n { value: 'C', title: `C) ${nextQuestion.options.C}` },\n { value: 'D', title: `D) ${nextQuestion.options.D}` },\n ]);\n\n if (selected !== null) {\n lines.push('', `User selected: ${selected}`);\n }\n }\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getExamHistory } from '../db/exam-attempts.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetExamHistory(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_exam_history',\n 'View all completed practice exam attempts with scores, pass/fail status, and per-domain breakdowns. Compare your progress across attempts.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const history = getExamHistory(db, userId);\n\n if (history.length === 0) {\n return {\n content: [{\n type: 'text' as const,\n text: [\n '═══ EXAM HISTORY ═══',\n '',\n 'No completed practice exams yet.',\n '',\n 'Use start_practice_exam to take your first 60-question practice exam.',\n 'Questions are weighted by domain — just like the real exam.',\n ].join('\\n'),\n }],\n };\n }\n\n const lines: string[] = [\n '═══ EXAM HISTORY ═══',\n '',\n `Total Attempts: ${history.length}`,\n `Best Score: ${Math.max(...history.map(h => h.score))}/1000`,\n `Latest Score: ${history[0].score}/1000`,\n '',\n ];\n\n for (const [i, attempt] of history.entries()) {\n const label = i === 0 ? ' (latest)' : '';\n lines.push(`─── Attempt #${history.length - i}${label} ───`);\n lines.push(` Date: ${attempt.completedAt ?? attempt.startedAt}`);\n lines.push(` Score: ${attempt.score}/1000 ${attempt.passed ? '✅ PASSED' : '❌ FAILED'}`);\n lines.push(` Correct: ${attempt.correctAnswers}/${attempt.totalQuestions} (${Math.round((attempt.correctAnswers / attempt.totalQuestions) * 100)}%)`);\n lines.push('');\n lines.push(' Domain Scores:');\n\n const scores = attempt.domainScores;\n for (const key of Object.keys(scores).sort()) {\n const ds = scores[key];\n lines.push(` D${ds.domainId}: ${ds.domainTitle} — ${ds.correctAnswers}/${ds.totalQuestions} (${ds.accuracyPercent}%)`);\n }\n\n // Show improvement from previous attempt\n if (i < history.length - 1) {\n const previous = history[i + 1];\n const diff = attempt.score - previous.score;\n const arrow = diff > 0 ? '↑' : diff < 0 ? '↓' : '→';\n lines.push('');\n lines.push(` Change from previous: ${arrow} ${diff > 0 ? '+' : ''}${diff} points`);\n }\n\n lines.push('');\n }\n\n // Trend summary\n if (history.length >= 2) {\n const latest = history[0].score;\n const first = history[history.length - 1].score;\n const totalImprovement = latest - first;\n lines.push('─── Overall Trend ───');\n lines.push(` First attempt: ${first}/1000`);\n lines.push(` Latest attempt: ${latest}/1000`);\n lines.push(` Total improvement: ${totalImprovement > 0 ? '+' : ''}${totalImprovement} points`);\n }\n\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions, loadHandout, loadCurriculum } from '../data/loader.js';\n\nconst FOLLOW_UP_ACTIONS = ['next', 'code_example', 'concept', 'handout', 'project', 'why_wrong'] as const;\n\nconst DOMAIN_PROJECT_MAP: Readonly<Record<number, string>> = {\n 1: 'd1-agentic',\n 2: 'd2-tools',\n 3: 'd3-config',\n 4: 'd4-prompts',\n 5: 'd5-context',\n} as const;\n\nfunction extractSection(markdown: string, sectionName: string): string | null {\n const pattern = new RegExp(`^## ${sectionName}\\\\b`, 'm');\n const match = pattern.exec(markdown);\n if (!match) return null;\n\n const startIndex = match.index + match[0].length;\n const nextSectionMatch = /^## /m.exec(markdown.slice(startIndex));\n const endIndex = nextSectionMatch ? startIndex + nextSectionMatch.index : markdown.length;\n\n return markdown.slice(startIndex, endIndex).trim();\n}\n\nfunction findQuestion(questionId: string) {\n const allQuestions = loadQuestions();\n return allQuestions.find((q) => q.id === questionId) ?? null;\n}\n\nexport function registerFollowUp(server: McpServer, _db: Database.Database, _userConfig: UserConfig): void {\n server.tool(\n 'follow_up',\n 'Handle post-answer follow-up actions. Use after submit_answer to explore concepts, code examples, handouts, or reference projects.',\n {\n questionId: z.string().describe('The question ID from the previous answer'),\n action: z.enum(FOLLOW_UP_ACTIONS).describe('The follow-up action to take'),\n },\n async ({ questionId, action }) => {\n const question = findQuestion(questionId);\n\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Question not found', questionId }) }],\n isError: true,\n };\n }\n\n switch (action) {\n case 'next': {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n instruction: 'Call get_practice_question to get the next question.',\n taskStatement: question.taskStatement,\n domainId: question.domainId,\n }, null, 2),\n }],\n };\n }\n\n case 'code_example': {\n const handout = loadHandout(question.taskStatement);\n if (!handout) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n const codeExample = extractSection(handout, 'Code Example');\n if (!codeExample) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No Code Example section found in handout', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n taskStatement: question.taskStatement,\n codeExample,\n }, null, 2),\n }],\n };\n }\n\n case 'concept': {\n const handout = loadHandout(question.taskStatement);\n if (!handout) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n const concept = extractSection(handout, 'Concept');\n if (!concept) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No Concept section found in handout', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n taskStatement: question.taskStatement,\n concept,\n }, null, 2),\n }],\n };\n }\n\n case 'handout': {\n const handout = loadHandout(question.taskStatement);\n if (!handout) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n taskStatement: question.taskStatement,\n handout,\n }, null, 2),\n }],\n };\n }\n\n case 'project': {\n const projectId = DOMAIN_PROJECT_MAP[question.domainId] ?? null;\n if (!projectId) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No reference project mapped for this domain', domainId: question.domainId }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n instruction: 'Call scaffold_project to explore the reference project for this domain.',\n projectId,\n domainId: question.domainId,\n }, null, 2),\n }],\n };\n }\n\n case 'why_wrong': {\n const incorrectOptions = Object.entries(question.whyWrongMap)\n .filter(([key]) => key !== question.correctAnswer)\n .reduce<Record<string, string>>((acc, [key, value]) => {\n if (value) {\n return { ...acc, [key]: value };\n }\n return acc;\n }, {});\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n questionId: question.id,\n correctAnswer: question.correctAnswer,\n explanation: question.explanation,\n whyOthersAreWrong: incorrectOptions,\n }, null, 2),\n }],\n };\n }\n }\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { CRITERIA } from '../data/criteria.js';\nimport { getActiveBuild, createBuild, updateBuildTheme } from '../db/capstone.js';\nimport { ensureUser } from '../db/users.js';\n\nfunction formatCriteria(): string {\n const lines: string[] = [];\n let currentDomain = 0;\n\n for (const criterion of CRITERIA) {\n if (criterion.domain !== currentDomain) {\n currentDomain = criterion.domain;\n if (lines.length > 0) lines.push('');\n lines.push(`Domain ${criterion.domain}: ${criterion.domainName}`);\n }\n lines.push(` ${criterion.id} — ${criterion.title}: ${criterion.description}`);\n }\n\n return lines.join('\\n');\n}\n\nfunction buildResponse(theme: string | null): string {\n const sections: string[] = [\n '=== GUIDED CAPSTONE BUILD ===',\n '',\n '--- 30 Architectural Criteria ---',\n '',\n formatCriteria(),\n ];\n\n if (theme) {\n sections.push(\n '',\n '--- Your Project Theme ---',\n theme,\n '',\n '--- Instructions ---',\n \"Review the criteria above against your project idea. Claude will analyze\",\n \"which criteria are naturally covered and suggest modifications for any gaps.\",\n \"When you're satisfied with coverage, use capstone_build_step with action\",\n \"'confirm' to begin building.\",\n );\n } else {\n sections.push(\n '',\n '--- Instructions ---',\n 'Choose a project theme that excites you. The best capstone projects are ones',\n 'you actually want to build. Provide your theme using start_capstone_build',\n \"with a 'theme' parameter, and Claude will analyze how well it covers the\",\n '30 criteria above.',\n );\n }\n\n return sections.join('\\n');\n}\n\nexport function registerStartCapstoneBuild(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'start_capstone_build',\n 'Start or refine a guided capstone build. Build your own project while learning all 30 certification task statements hands-on.',\n {\n theme: z.string().optional().describe(\"Your project idea or theme. Omit to see the 30 criteria first.\"),\n },\n async ({ theme }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n // Case 1: No theme — return criteria with instructions\n if (!theme) {\n return {\n content: [{ type: 'text' as const, text: buildResponse(null) }],\n };\n }\n\n const activeBuild = getActiveBuild(db, userId);\n\n // Case 4: Active build in 'building' status — error\n if (activeBuild && activeBuild.status === 'building') {\n return {\n content: [{\n type: 'text' as const,\n text: \"You have an active build in progress. Use capstone_build_step with action 'abandon' to start over.\",\n }],\n isError: true,\n };\n }\n\n // Case 3: Active build in 'shaping' status — update theme\n if (activeBuild && activeBuild.status === 'shaping') {\n updateBuildTheme(db, activeBuild.id, theme);\n return {\n content: [{ type: 'text' as const, text: buildResponse(theme) }],\n };\n }\n\n // Case 2: No active build — create new build\n createBuild(db, userId, theme);\n return {\n content: [{ type: 'text' as const, text: buildResponse(theme) }],\n };\n }\n );\n}\n","export interface Criterion {\n readonly id: string;\n readonly title: string;\n readonly domain: number;\n readonly domainName: string;\n readonly description: string;\n}\n\nconst DOMAIN_NAMES: Readonly<Record<number, string>> = {\n 1: 'Agentic Architecture & Orchestration',\n 2: 'Tool Design & MCP Integration',\n 3: 'Claude Code Configuration & Workflows',\n 4: 'Prompt Engineering & Structured Output',\n 5: 'Context Management & Reliability',\n} as const;\n\nexport const CRITERIA: readonly Criterion[] = [\n // Domain 1: Agentic Architecture & Orchestration\n {\n id: '1.1',\n title: 'Design and implement agentic loops for autonomous task execution',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Understanding the agentic loop lifecycle: sending requests, inspecting stop_reason, executing tools, and returning results.',\n },\n {\n id: '1.2',\n title: 'Orchestrate multi-agent systems with coordinator-subagent patterns',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Hub-and-spoke architecture, isolated context, task decomposition, and result aggregation.',\n },\n {\n id: '1.3',\n title: 'Configure subagent invocation, context passing, and spawning',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Task tool, allowedTools, explicit context passing, parallel subagent execution.',\n },\n {\n id: '1.4',\n title: 'Implement multi-step workflows with enforcement and handoff patterns',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Programmatic enforcement vs prompt-based guidance, structured handoff protocols.',\n },\n {\n id: '1.5',\n title: 'Apply Agent SDK hooks for tool call interception and data normalization',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'PostToolUse hooks, tool call interception, deterministic vs probabilistic compliance.',\n },\n {\n id: '1.6',\n title: 'Design task decomposition strategies for complex workflows',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Prompt chaining vs dynamic decomposition, per-file analysis vs cross-file integration.',\n },\n {\n id: '1.7',\n title: 'Manage session state, resumption, and forking',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Named sessions, fork_session, structured summaries vs stale context.',\n },\n\n // Domain 2: Tool Design & MCP Integration\n {\n id: '2.1',\n title: 'Design effective tool interfaces with clear descriptions and boundaries',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Tool descriptions as selection mechanism, disambiguation, splitting vs consolidating.',\n },\n {\n id: '2.2',\n title: 'Implement structured error responses for MCP tools',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'isError flag, error categories, retryable vs non-retryable, structured metadata.',\n },\n {\n id: '2.3',\n title: 'Distribute tools appropriately across agents and configure tool choice',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Scoped tool access, tool_choice options, forced selection patterns.',\n },\n {\n id: '2.4',\n title: 'Integrate MCP servers into Claude Code and agent workflows',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Project vs user scope, .mcp.json, environment variable expansion, MCP resources.',\n },\n {\n id: '2.5',\n title: 'Select and apply built-in tools effectively',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Grep vs Glob vs Read/Write/Edit, incremental codebase understanding.',\n },\n\n // Domain 3: Claude Code Configuration & Workflows\n {\n id: '3.1',\n title: 'Configure CLAUDE.md files with appropriate hierarchy and scoping',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'User-level, project-level, directory-level, @import syntax, .claude/rules/.',\n },\n {\n id: '3.2',\n title: 'Create and configure custom slash commands and skills',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'Project vs user scope, context: fork, allowed-tools, argument-hint frontmatter.',\n },\n {\n id: '3.3',\n title: 'Apply path-specific rules for conditional convention loading',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'YAML frontmatter paths, glob patterns, conditional activation.',\n },\n {\n id: '3.4',\n title: 'Determine when to use plan mode vs direct execution',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'Complexity assessment, architectural decisions, Explore subagent.',\n },\n {\n id: '3.5',\n title: 'Apply iterative refinement techniques for progressive improvement',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'Input/output examples, test-driven iteration, interview pattern.',\n },\n {\n id: '3.6',\n title: 'Integrate Claude Code into CI/CD pipelines',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n '-p flag, --output-format json, --json-schema, session context isolation.',\n },\n\n // Domain 4: Prompt Engineering & Structured Output\n {\n id: '4.1',\n title: 'Design prompts with explicit criteria to improve precision',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Explicit criteria vs vague instructions, false positive management.',\n },\n {\n id: '4.2',\n title: 'Apply few-shot prompting to improve output consistency',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Targeted examples, ambiguous case handling, format demonstration.',\n },\n {\n id: '4.3',\n title: 'Enforce structured output using tool use and JSON schemas',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'tool_use with schemas, tool_choice options, nullable fields, enum patterns.',\n },\n {\n id: '4.4',\n title: 'Implement validation, retry, and feedback loops',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Retry-with-error-feedback, limits of retry, detected_pattern tracking.',\n },\n {\n id: '4.5',\n title: 'Design efficient batch processing strategies',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Message Batches API, latency tolerance, custom_id, failure handling.',\n },\n {\n id: '4.6',\n title: 'Design multi-instance and multi-pass review architectures',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Self-review limitations, independent review instances, per-file + cross-file passes.',\n },\n\n // Domain 5: Context Management & Reliability\n {\n id: '5.1',\n title: 'Manage conversation context to preserve critical information',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Progressive summarization risks, lost-in-the-middle, tool output trimming.',\n },\n {\n id: '5.2',\n title: 'Design effective escalation and ambiguity resolution patterns',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Escalation triggers, customer preferences, sentiment unreliability.',\n },\n {\n id: '5.3',\n title: 'Implement error propagation strategies across multi-agent systems',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Structured error context, access failures vs empty results, partial results.',\n },\n {\n id: '5.4',\n title: 'Manage context effectively in large codebase exploration',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Context degradation, scratchpad files, subagent delegation, /compact.',\n },\n {\n id: '5.5',\n title: 'Design human review workflows and confidence calibration',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Stratified sampling, field-level confidence, accuracy by document type.',\n },\n {\n id: '5.6',\n title: 'Preserve information provenance and handle uncertainty in synthesis',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Claim-source mappings, conflict annotation, temporal data handling.',\n },\n] as const;\n","import crypto from 'node:crypto';\nimport type Database from 'better-sqlite3';\nimport type { CapstoneBuild, CapstoneBuildStep, BuildStepTemplate, BuildStepUpdates } from '../types.js';\n\nexport function getActiveBuild(db: Database.Database, userId: string): CapstoneBuild | null {\n const row = db.prepare(\n `SELECT * FROM capstone_builds WHERE userId = ? AND status IN ('shaping', 'building') ORDER BY createdAt DESC LIMIT 1`\n ).get(userId) as CapstoneBuild | undefined;\n return row ?? null;\n}\n\nexport function createBuild(db: Database.Database, userId: string, theme: string): CapstoneBuild {\n const id = crypto.randomUUID();\n const now = new Date().toISOString();\n db.prepare(\n `INSERT INTO capstone_builds (id, userId, theme, currentStep, status, themeValidated, createdAt, updatedAt)\n VALUES (?, ?, ?, 0, 'shaping', 0, ?, ?)`\n ).run(id, userId, theme, now, now);\n return db.prepare('SELECT * FROM capstone_builds WHERE id = ?').get(id) as CapstoneBuild;\n}\n\nexport function updateBuildTheme(db: Database.Database, buildId: string, theme: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET theme = ?, updatedAt = ? WHERE id = ?`\n ).run(theme, now, buildId);\n}\n\nexport function confirmBuild(db: Database.Database, buildId: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET status = 'building', themeValidated = 1, currentStep = 1, updatedAt = ? WHERE id = ?`\n ).run(now, buildId);\n}\n\nexport function abandonBuild(db: Database.Database, buildId: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET status = 'abandoned', updatedAt = ? WHERE id = ?`\n ).run(now, buildId);\n}\n\nexport function completeBuild(db: Database.Database, buildId: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET status = 'completed', updatedAt = ? WHERE id = ?`\n ).run(now, buildId);\n}\n\nexport function getBuildStep(db: Database.Database, buildId: string, stepIndex: number): CapstoneBuildStep | null {\n const row = db.prepare(\n `SELECT * FROM capstone_build_steps WHERE buildId = ? AND stepIndex = ?`\n ).get(buildId, stepIndex) as CapstoneBuildStep | undefined;\n return row ?? null;\n}\n\nexport function createBuildSteps(db: Database.Database, buildId: string, steps: readonly BuildStepTemplate[]): void {\n const now = new Date().toISOString();\n const insert = db.prepare(\n `INSERT INTO capstone_build_steps (id, buildId, stepIndex, fileName, taskStatements, quizQuestionIds, quizCompleted, buildCompleted, walkthroughViewed, createdAt, updatedAt)\n VALUES (?, ?, ?, ?, ?, NULL, 0, 0, 0, ?, ?)`\n );\n const insertAll = db.transaction((stepsToInsert: readonly BuildStepTemplate[]) => {\n for (const step of stepsToInsert) {\n insert.run(\n crypto.randomUUID(),\n buildId,\n step.stepIndex,\n step.fileName,\n JSON.stringify(step.taskStatements),\n now,\n now\n );\n }\n });\n insertAll(steps);\n}\n\nexport function updateBuildStep(db: Database.Database, stepId: string, updates: Partial<BuildStepUpdates>): void {\n const now = new Date().toISOString();\n const setClauses: string[] = ['updatedAt = ?'];\n const params: (string | number)[] = [now];\n\n if (updates.quizCompleted !== undefined) {\n setClauses.push('quizCompleted = ?');\n params.push(updates.quizCompleted);\n }\n if (updates.buildCompleted !== undefined) {\n setClauses.push('buildCompleted = ?');\n params.push(updates.buildCompleted);\n }\n if (updates.walkthroughViewed !== undefined) {\n setClauses.push('walkthroughViewed = ?');\n params.push(updates.walkthroughViewed);\n }\n\n params.push(stepId);\n db.prepare(`UPDATE capstone_build_steps SET ${setClauses.join(', ')} WHERE id = ?`).run(...params);\n}\n\nexport function setQuizQuestionIds(db: Database.Database, stepId: string, questionIds: readonly string[]): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_build_steps SET quizQuestionIds = ?, updatedAt = ? WHERE id = ?`\n ).run(JSON.stringify(questionIds), now, stepId);\n}\n\nexport function advanceBuildStep(db: Database.Database, buildId: string, nextStep: number): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET currentStep = ?, updatedAt = ? WHERE id = ?`\n ).run(nextStep, now, buildId);\n}\n\nexport function getBuildSteps(db: Database.Database, buildId: string): readonly CapstoneBuildStep[] {\n return db.prepare(\n `SELECT * FROM capstone_build_steps WHERE buildId = ? ORDER BY stepIndex ASC`\n ).all(buildId) as CapstoneBuildStep[];\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, CapstoneBuild, CapstoneBuildStep } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { BUILD_STEPS } from '../data/build-steps.js';\nimport { CRITERIA } from '../data/criteria.js';\nimport { ensureUser } from '../db/users.js';\nimport {\n getActiveBuild,\n confirmBuild,\n createBuildSteps,\n getBuildStep,\n setQuizQuestionIds,\n updateBuildStep,\n advanceBuildStep,\n completeBuild,\n abandonBuild,\n getBuildSteps,\n} from '../db/capstone.js';\nimport { elicitSingleSelect } from './elicit.js';\n\nconst ACTIONS = ['confirm', 'quiz', 'build', 'next', 'status', 'abandon'] as const;\n\nconst TOTAL_STEPS = 18;\n\nfunction errorResponse(message: string) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: message }) }],\n isError: true,\n };\n}\n\nfunction textResponse(data: unknown) {\n return {\n content: [{ type: 'text' as const, text: typeof data === 'string' ? data : JSON.stringify(data, null, 2) }],\n };\n}\n\nfunction getStepTemplate(stepIndex: number) {\n return BUILD_STEPS.find((s) => s.stepIndex === stepIndex) ?? null;\n}\n\nfunction formatStepPreview(step: CapstoneBuildStep, template: ReturnType<typeof getStepTemplate>) {\n const taskIds = JSON.parse(step.taskStatements) as readonly string[];\n const criteria = taskIds\n .map((id) => CRITERIA.find((c) => c.id === id))\n .filter(Boolean);\n\n return [\n `=== Step ${step.stepIndex}/${TOTAL_STEPS}: ${step.fileName} ===`,\n '',\n `Description: ${template?.description ?? 'N/A'}`,\n '',\n '--- Task Statements ---',\n ...criteria.map((c) => ` ${c!.id}: ${c!.title}`),\n '',\n 'Next action: Call capstone_build_step with action \"quiz\" to get quiz questions for this step.',\n ].join('\\n');\n}\n\nfunction shuffleArray<T>(arr: readonly T[]): readonly T[] {\n const copy = [...arr];\n for (let i = copy.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [copy[i], copy[j]] = [copy[j], copy[i]];\n }\n return copy;\n}\n\nfunction getAnsweredQuestionIdsForBuild(db: Database.Database, userId: string, questionIds: readonly string[]): Set<string> {\n if (questionIds.length === 0) return new Set();\n const placeholders = questionIds.map(() => '?').join(', ');\n const rows = db.prepare(\n `SELECT DISTINCT questionId FROM answers WHERE userId = ? AND questionId IN (${placeholders})`\n ).all(userId, ...questionIds) as Array<{ questionId: string }>;\n return new Set(rows.map((r) => r.questionId));\n}\n\nfunction handleConfirm(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found. Use capstone_theme to start a new build.');\n }\n if (build.status !== 'shaping') {\n return errorResponse(`Build is already in \"${build.status}\" status. Only \"shaping\" builds can be confirmed.`);\n }\n\n confirmBuild(db, build.id);\n createBuildSteps(db, build.id, BUILD_STEPS);\n\n const step = getBuildStep(db, build.id, 1);\n if (!step) {\n return errorResponse('Failed to create build steps.');\n }\n\n const template = getStepTemplate(1);\n return textResponse(formatStepPreview(step, template));\n}\n\nfunction handleQuiz(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n if (build.status !== 'building') {\n return errorResponse(`Build must be in \"building\" status to get quiz questions. Current status: \"${build.status}\".`);\n }\n\n const step = getBuildStep(db, build.id, build.currentStep);\n if (!step) {\n return errorResponse(`Build step ${build.currentStep} not found.`);\n }\n\n if (step.quizCompleted === 1) {\n return errorResponse('Quiz already completed for this step. Use action \"build\" to get build instructions.');\n }\n\n const taskIds = JSON.parse(step.taskStatements) as readonly string[];\n const allQuestions = loadQuestions();\n const stepQuestions = allQuestions.filter((q) => taskIds.includes(q.taskStatement));\n\n if (stepQuestions.length === 0) {\n return errorResponse(`No questions found for task statements: ${taskIds.join(', ')}`);\n }\n\n const shuffled = shuffleArray(stepQuestions);\n const quizCount = Math.min(shuffled.length, taskIds.length >= 3 ? 3 : 2);\n const selected = shuffled.slice(0, quizCount);\n const selectedIds = selected.map((q) => q.id);\n\n setQuizQuestionIds(db, step.id, selectedIds);\n\n const formattedQuestions = selected.map((q) => ({\n questionId: q.id,\n taskStatement: q.taskStatement,\n difficulty: q.difficulty,\n scenario: q.scenario,\n text: q.text,\n options: q.options,\n }));\n\n return textResponse({\n step: step.stepIndex,\n fileName: step.fileName,\n quizQuestions: formattedQuestions,\n instruction: 'Answer each question using the submit_answer tool.',\n });\n}\n\nfunction handleBuild(db: Database.Database, userId: string, build: CapstoneBuild): ReturnType<typeof textResponse> {\n const step = getBuildStep(db, build.id, build.currentStep);\n if (!step) {\n return errorResponse(`Build step ${build.currentStep} not found.`);\n }\n\n if (step.quizQuestionIds) {\n const questionIds = JSON.parse(step.quizQuestionIds) as readonly string[];\n const answered = getAnsweredQuestionIdsForBuild(db, userId, questionIds);\n const remaining = questionIds.filter((id) => !answered.has(id));\n\n if (remaining.length > 0) {\n return errorResponse(\n `Not all quiz questions answered. Remaining question IDs: ${remaining.join(', ')}. Use submit_answer to answer them first.`\n );\n }\n\n if (step.quizCompleted !== 1) {\n updateBuildStep(db, step.id, { quizCompleted: 1 });\n }\n }\n\n updateBuildStep(db, step.id, { buildCompleted: 1 });\n\n const template = getStepTemplate(build.currentStep);\n const taskIds = JSON.parse(step.taskStatements) as readonly string[];\n const criteria = taskIds\n .map((id) => CRITERIA.find((c) => c.id === id))\n .filter(Boolean);\n\n const taskDetails = criteria.map((c) => [\n ` ${c!.id}: ${c!.title}`,\n ` ${c!.description}`,\n ` Code hints: ${template?.codeHints ?? 'N/A'}`,\n ].join('\\n')).join('\\n\\n');\n\n const output = [\n `=== Step ${build.currentStep}/${TOTAL_STEPS}: ${step.fileName} ===`,\n '',\n `Theme: ${build.theme}`,\n `Task Statements: ${taskIds.join(', ')}`,\n '',\n '--- Build Instructions ---',\n `Generate the code for ${step.fileName} themed to the user's project above.`,\n 'The code should demonstrate these certification concepts:',\n '',\n taskDetails,\n '',\n 'After generating the code, provide a walkthrough explaining each section:',\n '- What the code does',\n '- Which task statement it demonstrates',\n '- How it connects to the broader architecture',\n '',\n '--- Task Statement Details ---',\n ...criteria.map((c) => `${c!.id} — ${c!.title}: ${c!.description}`),\n ].join('\\n');\n\n return textResponse(output);\n}\n\nfunction handleNext(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n if (build.status !== 'building') {\n return errorResponse(`Build must be in \"building\" status. Current status: \"${build.status}\".`);\n }\n\n const step = getBuildStep(db, build.id, build.currentStep);\n if (!step) {\n return errorResponse(`Build step ${build.currentStep} not found.`);\n }\n if (step.buildCompleted !== 1) {\n return errorResponse('Current step build is not completed. Use action \"build\" first.');\n }\n\n if (build.currentStep >= TOTAL_STEPS) {\n completeBuild(db, build.id);\n\n const allSteps = getBuildSteps(db, build.id);\n const completedCount = allSteps.filter((s) => s.buildCompleted === 1).length;\n\n return textResponse({\n status: 'completed',\n message: 'Congratulations! You have completed all 18 capstone build steps.',\n theme: build.theme,\n stepsCompleted: completedCount,\n totalSteps: TOTAL_STEPS,\n instruction: 'Review your completed project files and ensure all certification concepts are demonstrated.',\n });\n }\n\n const nextStepIndex = build.currentStep + 1;\n advanceBuildStep(db, build.id, nextStepIndex);\n\n const nextStep = getBuildStep(db, build.id, nextStepIndex);\n if (!nextStep) {\n return errorResponse(`Next step ${nextStepIndex} not found.`);\n }\n\n const template = getStepTemplate(nextStepIndex);\n return textResponse(formatStepPreview(nextStep, template));\n}\n\nfunction handleStatus(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n\n const allSteps = getBuildSteps(db, build.id);\n const completedSteps = allSteps.filter((s) => s.buildCompleted === 1);\n const remainingSteps = allSteps.filter((s) => s.buildCompleted !== 1);\n\n const coveredTaskIds = new Set(\n completedSteps.flatMap((s) => JSON.parse(s.taskStatements) as string[])\n );\n const totalCriteria = CRITERIA.length;\n const coveredCriteria = CRITERIA.filter((c) => coveredTaskIds.has(c.id)).length;\n\n return textResponse({\n buildId: build.id,\n theme: build.theme,\n status: build.status,\n currentStep: build.currentStep,\n stepsCompleted: completedSteps.length,\n stepsRemaining: remainingSteps.length,\n totalSteps: TOTAL_STEPS,\n criteriaCoverage: `${coveredCriteria}/${totalCriteria}`,\n completedFiles: completedSteps.map((s) => s.fileName),\n remainingFiles: remainingSteps.map((s) => s.fileName),\n });\n}\n\nfunction handleAbandon(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found to abandon.');\n }\n\n abandonBuild(db, build.id);\n\n return textResponse({\n status: 'abandoned',\n message: `Build \"${build.theme}\" has been abandoned.`,\n buildId: build.id,\n });\n}\n\nfunction appendSelectedAction(\n response: ReturnType<typeof textResponse>,\n selected: string | null,\n): ReturnType<typeof textResponse> {\n if (!selected) return response;\n\n const existingText = response.content[0].text;\n return {\n ...response,\n content: [{ type: 'text' as const, text: `${existingText}\\n\\nUser selected next action: ${selected}` }],\n };\n}\n\nexport function registerCapstoneBuildStep(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'capstone_build_step',\n 'Drive your guided capstone build — quiz, build, and advance through 18 progressive steps.',\n {\n action: z.enum(ACTIONS).describe('The build action: confirm, quiz, build, next, status, or abandon'),\n },\n async ({ action }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n switch (action) {\n case 'confirm': {\n const result = handleConfirm(db, userId);\n if ('isError' in result) return result;\n const selected = await elicitSingleSelect(\n server,\n 'Build confirmed! What would you like to do next?',\n 'nextAction',\n [{ value: 'quiz', title: 'Start the first quiz' }],\n );\n return appendSelectedAction(result, selected);\n }\n\n case 'quiz':\n return handleQuiz(db, userId);\n\n case 'build': {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n if (build.status !== 'building') {\n return errorResponse(`Build must be in \"building\" status. Current status: \"${build.status}\".`);\n }\n const result = handleBuild(db, userId, build);\n if ('isError' in result) return result;\n const selected = await elicitSingleSelect(\n server,\n 'Build instructions generated. What would you like to do next?',\n 'nextAction',\n [\n { value: 'next', title: 'Advance to the next step' },\n { value: 'status', title: 'Check build progress' },\n ],\n );\n return appendSelectedAction(result, selected);\n }\n\n case 'next': {\n const result = handleNext(db, userId);\n if ('isError' in result) return result;\n const selected = await elicitSingleSelect(\n server,\n 'Step advanced. What would you like to do next?',\n 'nextAction',\n [\n { value: 'quiz', title: 'Start this step\\'s quiz' },\n { value: 'status', title: 'Check build progress' },\n ],\n );\n return appendSelectedAction(result, selected);\n }\n\n case 'status':\n return handleStatus(db, userId);\n\n case 'abandon':\n return handleAbandon(db, userId);\n }\n }\n );\n}\n","export interface BuildStep {\n readonly stepIndex: number;\n readonly fileName: string;\n readonly taskStatements: readonly string[];\n readonly description: string;\n readonly codeHints: string;\n}\n\nexport const BUILD_STEPS: readonly BuildStep[] = [\n {\n stepIndex: 1,\n fileName: 'CLAUDE.md, .claude/',\n taskStatements: ['3.1', '3.2', '3.3'],\n description: 'Project config and rules',\n codeHints:\n 'Generate a CLAUDE.md with hierarchical instructions, @import references, and .claude/rules/ with path-scoped YAML frontmatter. Include a custom slash command definition.',\n },\n {\n stepIndex: 2,\n fileName: 'package.json, tsconfig.json',\n taskStatements: ['3.4'],\n description: 'Project setup and CI hooks',\n codeHints:\n 'Set up TypeScript project configuration with strict compiler options, lint/test scripts suitable for plan-mode assessment, and pre-commit hooks.',\n },\n {\n stepIndex: 3,\n fileName: 'src/server.ts',\n taskStatements: ['2.1', '2.2'],\n description: 'MCP server with tool registration',\n codeHints:\n 'Create an MCP server entry point that registers tools with clear descriptions and boundaries, and returns structured error responses with isError flags.',\n },\n {\n stepIndex: 4,\n fileName: 'src/tools/',\n taskStatements: ['2.1', '2.3', '2.5'],\n description: 'Tool definitions and scoping',\n codeHints:\n 'Define tool modules with scoped access per agent, tool_choice configuration, and demonstrate effective use of built-in tools like Grep, Glob, and Read.',\n },\n {\n stepIndex: 5,\n fileName: 'src/error-handling.ts',\n taskStatements: ['2.2'],\n description: 'Error boundaries and recovery',\n codeHints:\n 'Implement error boundary utilities that categorize errors as retryable vs non-retryable, attach structured metadata, and format MCP-compliant error responses.',\n },\n {\n stepIndex: 6,\n fileName: 'src/coordinator.ts',\n taskStatements: ['1.1', '1.2', '1.6'],\n description: 'Main agentic loop',\n codeHints:\n 'Build a coordinator that runs the agentic loop (send request, inspect stop_reason, execute tools, return results) with hub-and-spoke orchestration and task decomposition.',\n },\n {\n stepIndex: 7,\n fileName: 'src/subagents/',\n taskStatements: ['1.3', '1.4'],\n description: 'Subagent definitions and routing',\n codeHints:\n 'Define subagent configurations with allowedTools, explicit context passing, and structured handoff protocols for multi-step workflow enforcement.',\n },\n {\n stepIndex: 8,\n fileName: 'src/hooks.ts',\n taskStatements: ['1.5'],\n description: 'Pre/post tool-use hooks',\n codeHints:\n 'Implement PostToolUse hooks that intercept tool calls for data normalization, demonstrating deterministic compliance checks vs probabilistic validation.',\n },\n {\n stepIndex: 9,\n fileName: 'src/workflow.ts',\n taskStatements: ['1.4', '1.6'],\n description: 'Multi-step workflows',\n codeHints:\n 'Create workflow orchestration with programmatic enforcement gates, prompt chaining stages, and per-file analysis that feeds into cross-file integration.',\n },\n {\n stepIndex: 10,\n fileName: 'src/session.ts',\n taskStatements: ['1.7'],\n description: 'Session and state management',\n codeHints:\n 'Implement session lifecycle with named sessions, fork_session for parallel exploration, and structured summaries to avoid stale context on resumption.',\n },\n {\n stepIndex: 11,\n fileName: 'src/prompts/system.ts',\n taskStatements: ['4.1', '4.2'],\n description: 'System prompts with few-shot',\n codeHints:\n 'Design system prompts with explicit criteria for precision, and embed few-shot examples that handle ambiguous cases and demonstrate expected output format.',\n },\n {\n stepIndex: 12,\n fileName: 'src/prompts/extraction.ts',\n taskStatements: ['4.3', '4.4'],\n description: 'Structured output and validation',\n codeHints:\n 'Enforce structured output via tool_use with JSON schemas and enum patterns, plus retry-with-error-feedback loops that track detected_pattern for progressive improvement.',\n },\n {\n stepIndex: 13,\n fileName: 'src/prompts/batch.ts',\n taskStatements: ['4.5', '4.6'],\n description: 'Batch processing and multi-pass',\n codeHints:\n 'Implement batch processing using the Message Batches API with custom_id tracking and failure handling, plus multi-pass review with independent instances.',\n },\n {\n stepIndex: 14,\n fileName: 'src/context/preservation.ts',\n taskStatements: ['5.1'],\n description: 'Context preservation strategies',\n codeHints:\n 'Implement context preservation that mitigates progressive summarization risks and lost-in-the-middle effects, with tool output trimming to retain critical information.',\n },\n {\n stepIndex: 15,\n fileName: 'src/context/triggers.ts',\n taskStatements: ['5.2'],\n description: 'Context refresh triggers',\n codeHints:\n 'Define escalation triggers and ambiguity resolution patterns that detect when context needs refreshing, using customer preference signals rather than unreliable sentiment.',\n },\n {\n stepIndex: 16,\n fileName: 'src/context/propagation.ts',\n taskStatements: ['5.3'],\n description: 'Cross-agent context propagation',\n codeHints:\n 'Implement structured error context propagation across agents, distinguishing access failures from empty results and handling partial result aggregation.',\n },\n {\n stepIndex: 17,\n fileName: 'src/context/scratchpad.ts',\n taskStatements: ['5.4'],\n description: 'Scratchpad and subagent delegation',\n codeHints:\n 'Build scratchpad file management for large codebase exploration, with subagent delegation to prevent context degradation and /compact integration.',\n },\n {\n stepIndex: 18,\n fileName: 'src/context/confidence.ts',\n taskStatements: ['5.5', '5.6'],\n description: 'Confidence calibration and synthesis',\n codeHints:\n 'Implement field-level confidence scoring with stratified sampling for human review, plus claim-source mappings with conflict annotation for provenance tracking.',\n },\n] as const;\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, CapstoneBuildStep } from '../types.js';\nimport { getActiveBuild, getBuildSteps } from '../db/capstone.js';\nimport { BUILD_STEPS } from '../data/build-steps.js';\nimport { CRITERIA } from '../data/criteria.js';\n\ninterface QuizStats {\n readonly domainId: number;\n readonly total: number;\n readonly correct: number;\n}\n\nfunction collectQuizQuestionIds(steps: readonly CapstoneBuildStep[]): readonly string[] {\n return steps.flatMap(step => {\n if (!step.quizQuestionIds) return [];\n const parsed = JSON.parse(step.quizQuestionIds) as readonly string[];\n return [...parsed];\n });\n}\n\nfunction getQuizPerformance(db: Database.Database, userId: string, questionIds: readonly string[]): readonly QuizStats[] {\n if (questionIds.length === 0) return [];\n\n const placeholders = questionIds.map(() => '?').join(', ');\n const rows = db.prepare(\n `SELECT domainId, COUNT(*) as total, SUM(CASE WHEN isCorrect THEN 1 ELSE 0 END) as correct\n FROM answers\n WHERE userId = ? AND questionId IN (${placeholders})\n GROUP BY domainId\n ORDER BY domainId ASC`\n ).all(userId, ...questionIds) as Array<{ domainId: number; total: number; correct: number }>;\n\n return rows.map(r => ({\n domainId: r.domainId,\n total: r.total,\n correct: r.correct ?? 0,\n }));\n}\n\nfunction countCoveredCriteria(completedSteps: readonly CapstoneBuildStep[]): number {\n const coveredIds = new Set<string>();\n for (const step of completedSteps) {\n if (!step.buildCompleted) continue;\n const taskStatements = JSON.parse(step.taskStatements) as readonly string[];\n for (const ts of taskStatements) {\n coveredIds.add(ts);\n }\n }\n return coveredIds.size;\n}\n\nfunction formatBuildingStatus(\n theme: string,\n currentStep: number,\n steps: readonly CapstoneBuildStep[],\n quizPerformance: readonly QuizStats[],\n): string {\n const totalSteps = BUILD_STEPS.length;\n const totalCriteria = CRITERIA.length;\n const coveredCriteria = countCoveredCriteria(steps);\n const remainingCriteria = totalCriteria - coveredCriteria;\n\n const stepLines = BUILD_STEPS.map(template => {\n const dbStep = steps.find(s => s.stepIndex === template.stepIndex);\n const isCompleted = dbStep?.buildCompleted === 1;\n const isCurrent = template.stepIndex === currentStep;\n const marker = isCompleted ? '[x]' : '[ ]';\n const suffix = isCurrent && !isCompleted ? ' \\u2190 current' : '';\n const criteria = template.taskStatements.join(', ');\n return ` ${marker} Step ${template.stepIndex}: ${template.fileName} (${criteria})${suffix}`;\n });\n\n const quizLines = quizPerformance.length > 0\n ? quizPerformance.map(q => {\n const pct = q.total > 0 ? Math.round((q.correct / q.total) * 100) : 0;\n return ` Domain ${q.domainId}: ${q.correct}/${q.total} correct (${pct}%)`;\n })\n : [' No quiz answers yet.'];\n\n const sections = [\n '=== CAPSTONE BUILD PROGRESS ===',\n '',\n `Theme: ${theme}`,\n 'Status: Building',\n `Current Step: ${currentStep}/${totalSteps}`,\n '',\n '--- Completed Steps ---',\n ...stepLines,\n '',\n '--- Criteria Coverage ---',\n ` Covered: ${coveredCriteria}/${totalCriteria} task statements`,\n ` Remaining: ${remainingCriteria} task statements`,\n '',\n '--- Quiz Performance ---',\n ...quizLines,\n ];\n\n return sections.join('\\n');\n}\n\nexport function registerCapstoneBuildStatus(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'capstone_build_status',\n 'Check your guided capstone build progress \\u2014 current step, criteria coverage, and quiz performance.',\n {},\n async () => {\n const userId = userConfig.userId;\n const build = getActiveBuild(db, userId);\n\n if (!build) {\n return {\n content: [{\n type: 'text' as const,\n text: 'No active capstone build found. Use start_capstone_build to begin a guided build.',\n }],\n };\n }\n\n if (build.status === 'shaping') {\n const lines = [\n '=== CAPSTONE BUILD STATUS ===',\n '',\n `Theme: ${build.theme}`,\n 'Status: Shaping',\n '',\n 'Your theme is being shaped. You can:',\n ' - Confirm it to start building',\n ' - Refine it with a new description',\n ];\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n };\n }\n\n // Status is 'building'\n const steps = getBuildSteps(db, build.id);\n const quizQuestionIds = collectQuizQuestionIds(steps);\n const quizPerformance = getQuizPerformance(db, userId, quizQuestionIds);\n\n const text = formatBuildingStatus(build.theme, build.currentStep, steps, quizPerformance);\n\n return {\n content: [{ type: 'text' as const, text }],\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { registerSubmitAnswer } from './submit-answer.js';\nimport { registerGetProgress } from './get-progress.js';\nimport { registerGetCurriculum } from './get-curriculum.js';\nimport { registerGetSectionDetails } from './get-section-details.js';\nimport { registerGetPracticeQuestion } from './get-practice-question.js';\nimport { registerStartAssessment } from './start-assessment.js';\nimport { registerGetWeakAreas } from './get-weak-areas.js';\nimport { registerGetStudyPlan } from './get-study-plan.js';\nimport { registerScaffoldProject } from './scaffold-project.js';\nimport { registerResetProgress } from './reset-progress.js';\nimport { registerStartPracticeExam } from './start-practice-exam.js';\nimport { registerSubmitExamAnswer } from './submit-exam-answer.js';\nimport { registerGetExamHistory } from './get-exam-history.js';\nimport { registerFollowUp } from './follow-up.js';\nimport { registerStartCapstoneBuild } from './start-capstone-build.js';\nimport { registerCapstoneBuildStep } from './capstone-build-step.js';\nimport { registerCapstoneBuildStatus } from './capstone-build-status.js';\n\nexport function registerTools(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n registerSubmitAnswer(server, db, userConfig);\n registerGetProgress(server, db, userConfig);\n registerGetCurriculum(server, db, userConfig);\n registerGetSectionDetails(server, db, userConfig);\n registerGetPracticeQuestion(server, db, userConfig);\n registerStartAssessment(server, db, userConfig);\n registerGetWeakAreas(server, db, userConfig);\n registerGetStudyPlan(server, db, userConfig);\n registerScaffoldProject(server, db, userConfig);\n registerResetProgress(server, db, userConfig);\n registerStartPracticeExam(server, db, userConfig);\n registerSubmitExamAnswer(server, db, userConfig);\n registerGetExamHistory(server, db, userConfig);\n registerFollowUp(server, db, userConfig);\n registerStartCapstoneBuild(server, db, userConfig);\n registerCapstoneBuildStep(server, db, userConfig);\n registerCapstoneBuildStatus(server, db, userConfig);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\n\nexport function registerPrompts(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.prompt(\n 'quiz_question',\n 'Present a certification exam question with clickable A/B/C/D options',\n { questionId: z.string().describe('Question ID to present') },\n async ({ questionId }) => {\n const questions = loadQuestions();\n const question = questions.find(q => q.id === questionId);\n if (!question) {\n return { messages: [{ role: 'user' as const, content: { type: 'text' as const, text: 'Question not found.' } }] };\n }\n return {\n messages: [{\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: `**${question.scenario}**\\n\\n${question.text}\\n\\n A) ${question.options.A}\\n B) ${question.options.B}\\n C) ${question.options.C}\\n D) ${question.options.D}\\n\\nSelect your answer (A/B/C/D):`,\n },\n }],\n };\n }\n );\n\n server.prompt(\n 'choose_mode',\n 'Select a study mode for the current session',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: 'How would you like to study?\\n\\n1. **Guided Capstone** — Work through the reference project touching all domains\\n2. **Dynamic Exercises** — Targeted questions based on your weak areas\\n3. **Quick Quiz** — Rapid-fire questions across all domains\\n4. **Review Weak Areas** — Focus on topics you\\'ve struggled with\\n\\nChoose a mode (1-4):',\n },\n }],\n })\n );\n\n server.prompt(\n 'assessment_question',\n 'Present an assessment question with A/B/C/D options',\n { questionId: z.string().describe('Assessment question ID'), questionNumber: z.string().describe('Current question number (1-15)') },\n async ({ questionId, questionNumber }) => {\n const question = loadQuestions().find(q => q.id === questionId);\n if (!question) return { messages: [{ role: 'user' as const, content: { type: 'text' as const, text: 'Question not found.' } }] };\n return {\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: `**Assessment Question ${questionNumber}/15**\\n\\n${question.scenario}\\n\\n${question.text}\\n\\n A) ${question.options.A}\\n B) ${question.options.B}\\n C) ${question.options.C}\\n D) ${question.options.D}\\n\\nSelect your answer:` },\n }],\n };\n }\n );\n\n server.prompt(\n 'choose_domain',\n 'Select which domain to study',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: 'Which domain would you like to study?\\n\\n1. **Agentic Architecture & Orchestration** (27%)\\n2. **Tool Design & MCP Integration** (18%)\\n3. **Claude Code Configuration & Workflows** (20%)\\n4. **Prompt Engineering & Structured Output** (20%)\\n5. **Context Management & Reliability** (15%)\\n\\nChoose a domain (1-5):' },\n }],\n })\n );\n\n server.prompt(\n 'choose_difficulty',\n 'Select question difficulty level',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: 'Choose your difficulty level:\\n\\n1. **Easy** — Concept recall and basic understanding\\n2. **Medium** — Applied scenarios requiring analysis\\n3. **Hard** — Complex multi-step reasoning\\n\\nSelect difficulty (1-3):' },\n }],\n })\n );\n\n server.prompt(\n 'post_answer_options',\n 'Present options after answering a question',\n { wasCorrect: z.string().describe('Whether the previous answer was correct') },\n async ({ wasCorrect }) => {\n const options = wasCorrect === 'true'\n ? '1. **Next Question** — Continue with the next question\\n2. **Explain Further** — Show a deeper explanation with code example\\n3. **View Handout** — Read the concept lesson for this topic\\n4. **Change Topic** — Switch to a different domain'\n : '1. **Next Question** — Continue with the next question\\n2. **Explain Why I Was Wrong** — Show a detailed explanation with code example\\n3. **View Concept Lesson** — Review the concept before continuing\\n4. **Try Similar Question** — Get another question on this same topic';\n return {\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: `What would you like to do next?\\n\\n${options}\\n\\nChoose an option (1-4):` },\n }],\n };\n }\n );\n\n server.prompt(\n 'skip_options',\n 'Present options to skip or customize the current content',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: 'This topic has a concept lesson before the questions.\\n\\n1. **Read Lesson** — Learn the concept first (recommended for new topics)\\n2. **Skip to Questions** — Go straight to practice questions\\n3. **Quick Summary** — Get a 3-line summary then start questions\\n\\nChoose an option (1-3):' },\n }],\n })\n );\n\n server.prompt(\n 'confirm_action',\n 'Confirm a destructive action like resetting progress',\n { action: z.string().describe('The action to confirm') },\n async ({ action }) => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: `Are you sure?\\n\\nThis will ${action}. This action cannot be undone.\\n\\n1. **Yes, proceed** — Confirm the action\\n2. **No, cancel** — Go back\\n\\nChoose (1-2):` },\n }],\n })\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadCurriculum, loadHandout } from '../data/loader.js';\nimport { recordHandoutView } from '../db/handout-views.js';\nimport { getQuizWidgetHtml } from '../ui/loader.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport function registerResources(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n // 1. Handouts as dynamic resource\n server.resource(\n 'handout',\n new ResourceTemplate('handout://{taskStatement}', {\n list: async () => {\n const curriculum = loadCurriculum();\n const resources = curriculum.domains.flatMap(d =>\n d.taskStatements.map(ts => ({\n uri: `handout://${ts.id}`,\n name: `${ts.id} — ${ts.title}`,\n mimeType: 'text/markdown' as const,\n }))\n );\n return { resources };\n },\n }),\n { mimeType: 'text/markdown' },\n async (uri, { taskStatement }) => {\n const ts = taskStatement as string;\n const content = loadHandout(ts);\n recordHandoutView(db, userConfig.userId, ts);\n return {\n contents: [{\n uri: uri.href,\n text: content ?? `Handout for ${ts} is not yet available.`,\n mimeType: 'text/markdown',\n }],\n };\n }\n );\n\n // 2. Reference projects as dynamic resource\n server.resource(\n 'reference-project',\n new ResourceTemplate('reference-project://{projectId}', {\n list: async () => ({\n resources: [\n { uri: 'reference-project://capstone', name: 'Capstone — Multi-Agent Research System', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d1-agentic', name: 'D1 Mini — Agentic Loop', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d2-tools', name: 'D2 Mini — Tool Design', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d3-config', name: 'D3 Mini — Claude Code Config', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d4-prompts', name: 'D4 Mini — Prompt Engineering', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d5-context', name: 'D5 Mini — Context Management', mimeType: 'text/markdown' as const },\n ],\n }),\n }),\n { mimeType: 'text/markdown' },\n async (uri, { projectId }) => {\n const id = projectId as string;\n const projectPath = path.join(__dirname, '..', '..', 'projects', id, 'README.md');\n const content = fs.existsSync(projectPath)\n ? fs.readFileSync(projectPath, 'utf-8')\n : `Reference project \"${id}\" is not yet available. It will be added in the content creation phase.`;\n return {\n contents: [{ uri: uri.href, text: content, mimeType: 'text/markdown' }],\n };\n }\n );\n\n // 3. Quiz widget UI resource (MCP App)\n server.resource(\n 'quiz-widget',\n 'ui://connectry-architect/quiz',\n { mimeType: 'text/html;profile=mcp-app' },\n async (uri) => ({\n contents: [{\n uri: uri.href,\n mimeType: 'text/html;profile=mcp-app',\n text: getQuizWidgetHtml(),\n }],\n }),\n );\n\n // 4. Exam info as static resource\n server.resource(\n 'exam-info',\n 'exam-info://overview',\n { mimeType: 'text/markdown' },\n async (uri) => ({\n contents: [{\n uri: uri.href,\n text: EXAM_INFO_MARKDOWN,\n mimeType: 'text/markdown',\n }],\n })\n );\n}\n\nconst EXAM_INFO_MARKDOWN = `# Claude Certified Architect — Foundations\n\n## Exam Format\n- Multiple choice (1 correct, 3 distractors)\n- Scenario-based questions (4 of 6 scenarios per exam)\n- Passing score: 720 / 1000\n\n## Domain Weightings\n| Domain | Weight |\n|--------|--------|\n| D1: Agentic Architecture & Orchestration | 27% |\n| D2: Tool Design & MCP Integration | 18% |\n| D3: Claude Code Configuration & Workflows | 20% |\n| D4: Prompt Engineering & Structured Output | 20% |\n| D5: Context Management & Reliability | 15% |\n\n## Exam Scenarios\n1. Customer Support Resolution Agent\n2. Code Generation with Claude Code\n3. Multi-Agent Research System\n4. Developer Productivity with Claude\n5. Claude Code for Continuous Integration\n6. Structured Data Extraction\n`;\n","import { readFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nlet quizWidgetHtml: string | null = null;\n\nexport function getQuizWidgetHtml(): string {\n if (!quizWidgetHtml) {\n quizWidgetHtml = readFileSync(resolve(__dirname, '../ui/quiz-widget.html'), 'utf-8');\n }\n return quizWidgetHtml;\n}\n"],"mappings":"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","names":["dbPath","db","fs","path","newEase","nextReviewAt","fs","path","db","db","db","db","db","db","server","db","userConfig","server","db","userConfig","server","db","userConfig","z","db","server","db","userConfig","z","z","server","db","userConfig","z","server","db","userConfig","server","db","userConfig","path","server","db","userConfig","path","fs","path","fileURLToPath","z","__dirname","server","z","server","db","userConfig","db","server","db","userConfig","z","server","db","userConfig","z","server","db","userConfig","z","server","z","z","crypto","db","server","db","userConfig","z","z","shuffleArray","db","server","userConfig","z","db","server","userConfig","server","db","userConfig","z","server","db","userConfig","z","fs","path","fileURLToPath","fileURLToPath","__dirname","__dirname","path","fileURLToPath","server","db","userConfig","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/db/store.ts","../src/db/schema.ts","../src/config.ts","../src/tools/submit-answer.ts","../src/tools/elicit.ts","../src/engine/grading.ts","../src/engine/spaced-repetition.ts","../src/data/loader.ts","../src/db/answers.ts","../src/db/mastery.ts","../src/db/review-schedule.ts","../src/db/users.ts","../src/ui/meta.ts","../src/tools/get-progress.ts","../src/tools/get-curriculum.ts","../src/tools/get-section-details.ts","../src/db/handout-views.ts","../src/tools/get-practice-question.ts","../src/engine/question-selector.ts","../src/tools/start-assessment.ts","../src/tools/get-weak-areas.ts","../src/engine/adaptive-path.ts","../src/tools/get-study-plan.ts","../src/tools/scaffold-project.ts","../src/tools/reset-progress.ts","../src/engine/exam-builder.ts","../src/db/exam-attempts.ts","../src/tools/start-practice-exam.ts","../src/tools/submit-exam-answer.ts","../src/tools/get-exam-history.ts","../src/tools/follow-up.ts","../src/tools/start-capstone-build.ts","../src/data/criteria.ts","../src/db/capstone.ts","../src/tools/capstone-build-step.ts","../src/data/build-steps.ts","../src/tools/capstone-build-status.ts","../src/tools/index.ts","../src/prompts/index.ts","../src/resources/index.ts","../src/ui/loader.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createDatabase, getDefaultDbPath } from './db/store.js';\nimport { loadOrCreateUserConfig } from './config.js';\nimport { registerTools } from './tools/index.js';\nimport { registerPrompts } from './prompts/index.js';\nimport { registerResources } from './resources/index.js';\n\nconst server = new McpServer({\n name: 'connectry-architect',\n version: '0.1.0',\n});\n\nconst dbPath = process.env['CONNECTRY_DB_PATH'] ?? getDefaultDbPath();\nconst db = createDatabase(dbPath);\nconst userConfig = loadOrCreateUserConfig();\n\nregisterTools(server, db, userConfig);\nregisterPrompts(server, db, userConfig);\nregisterResources(server, db, userConfig);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","import Database from 'better-sqlite3';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { SCHEMA_SQL } from './schema.js';\n\nexport function createDatabase(dbPath: string): Database.Database {\n const db = new Database(dbPath);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n db.pragma('synchronous = NORMAL');\n db.pragma('busy_timeout = 5000');\n db.exec(SCHEMA_SQL);\n return db;\n}\n\nexport function getDefaultDbPath(): string {\n const dir = path.join(\n process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.',\n '.connectry-architect'\n );\n fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, 'progress.db');\n}\n","export const SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS users (\n id TEXT PRIMARY KEY,\n displayName TEXT,\n createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n lastActivityAt DATETIME,\n assessmentCompleted BOOLEAN DEFAULT FALSE,\n learningPath TEXT\n);\n\nCREATE TABLE IF NOT EXISTS domain_mastery (\n userId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n domainId INTEGER NOT NULL,\n totalAttempts INTEGER DEFAULT 0,\n correctAttempts INTEGER DEFAULT 0,\n accuracyPercent REAL DEFAULT 0,\n masteryLevel TEXT DEFAULT 'unassessed',\n lastTestedAt DATETIME,\n FOREIGN KEY (userId) REFERENCES users(id),\n PRIMARY KEY (userId, taskStatement)\n);\n\nCREATE TABLE IF NOT EXISTS answers (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n userId TEXT NOT NULL,\n questionId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n domainId INTEGER NOT NULL,\n userAnswer TEXT NOT NULL,\n correctAnswer TEXT NOT NULL,\n isCorrect BOOLEAN NOT NULL,\n difficulty TEXT NOT NULL,\n answeredAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS review_schedule (\n userId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n nextReviewAt DATETIME NOT NULL,\n interval INTEGER DEFAULT 1,\n easeFactor REAL DEFAULT 2.5,\n consecutiveCorrect INTEGER DEFAULT 0,\n FOREIGN KEY (userId) REFERENCES users(id),\n PRIMARY KEY (userId, taskStatement)\n);\n\nCREATE TABLE IF NOT EXISTS study_sessions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n userId TEXT NOT NULL,\n startedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n endedAt DATETIME,\n domainId INTEGER,\n questionsAnswered INTEGER DEFAULT 0,\n correctAnswers INTEGER DEFAULT 0,\n mode TEXT,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS handout_views (\n userId TEXT NOT NULL,\n taskStatement TEXT NOT NULL,\n viewedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n timeSpentSeconds INTEGER DEFAULT 0,\n PRIMARY KEY (userId, taskStatement),\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS session_state (\n userId TEXT PRIMARY KEY,\n currentMode TEXT NOT NULL,\n currentDomain INTEGER,\n currentTaskStatement TEXT,\n currentQuestionIndex INTEGER DEFAULT 0,\n positionStack TEXT DEFAULT '[]',\n reviewQueueIds TEXT DEFAULT '[]',\n lastUpdatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS exam_attempts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n userId TEXT NOT NULL,\n startedAt DATETIME DEFAULT CURRENT_TIMESTAMP,\n completedAt DATETIME,\n totalQuestions INTEGER NOT NULL DEFAULT 60,\n correctAnswers INTEGER DEFAULT 0,\n score INTEGER DEFAULT 0,\n passed BOOLEAN DEFAULT FALSE,\n questionIds TEXT NOT NULL DEFAULT '[]',\n answeredQuestionIds TEXT NOT NULL DEFAULT '[]',\n domainScores TEXT NOT NULL DEFAULT '{}',\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS capstone_builds (\n id TEXT PRIMARY KEY,\n userId TEXT NOT NULL,\n theme TEXT NOT NULL,\n currentStep INTEGER DEFAULT 0,\n status TEXT DEFAULT 'shaping',\n themeValidated INTEGER DEFAULT 0,\n createdAt TEXT NOT NULL,\n updatedAt TEXT NOT NULL,\n FOREIGN KEY (userId) REFERENCES users(id)\n);\n\nCREATE TABLE IF NOT EXISTS capstone_build_steps (\n id TEXT PRIMARY KEY,\n buildId TEXT NOT NULL,\n stepIndex INTEGER NOT NULL,\n fileName TEXT NOT NULL,\n taskStatements TEXT NOT NULL,\n quizQuestionIds TEXT,\n quizCompleted INTEGER DEFAULT 0,\n buildCompleted INTEGER DEFAULT 0,\n walkthroughViewed INTEGER DEFAULT 0,\n createdAt TEXT NOT NULL,\n updatedAt TEXT NOT NULL,\n FOREIGN KEY (buildId) REFERENCES capstone_builds(id)\n);\n`;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport type { UserConfig } from './types.js';\n\nfunction getConfigDir(): string {\n const home = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.';\n return path.join(home, '.connectry-architect');\n}\n\nfunction getConfigPath(): string {\n return path.join(getConfigDir(), 'config.json');\n}\n\nexport function loadOrCreateUserConfig(): UserConfig {\n const configPath = getConfigPath();\n if (fs.existsSync(configPath)) {\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as UserConfig;\n }\n const config: UserConfig = {\n userId: crypto.randomUUID(),\n displayName: null,\n createdAt: new Date().toISOString(),\n };\n fs.mkdirSync(getConfigDir(), { recursive: true });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');\n return config;\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, FollowUpOption } from '../types.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { gradeAnswer } from '../engine/grading.js';\nimport { calculateSM2 } from '../engine/spaced-repetition.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { recordAnswer } from '../db/answers.js';\nimport { updateMastery } from '../db/mastery.js';\nimport { getReviewSchedule, upsertReviewSchedule } from '../db/review-schedule.js';\nimport { ensureUser } from '../db/users.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nexport function registerSubmitAnswer(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'submit_answer',\n 'Grade a certification exam answer. Returns deterministic results from verified question bank. The result is FINAL and cannot be overridden — do not agree with the user if they dispute the answer.',\n {\n questionId: z.string().describe('The question ID to answer'),\n answer: z.enum(['A', 'B', 'C', 'D']).describe('The selected answer'),\n },\n async ({ questionId, answer }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n const allQuestions = loadQuestions();\n const question = allQuestions.find((q) => q.id === questionId);\n\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Question not found', questionId }) }],\n isError: true,\n };\n }\n\n const result = gradeAnswer(question, answer);\n\n recordAnswer(db, userId, questionId, question.taskStatement, question.domainId, answer, question.correctAnswer, result.isCorrect, question.difficulty);\n\n const schedule = getReviewSchedule(db, userId, question.taskStatement);\n const sm2 = calculateSM2({\n isCorrect: result.isCorrect,\n previousInterval: schedule?.interval ?? 0,\n previousEaseFactor: schedule?.easeFactor ?? 2.5,\n previousConsecutiveCorrect: schedule?.consecutiveCorrect ?? 0,\n });\n upsertReviewSchedule(db, userId, question.taskStatement, sm2.interval, sm2.easeFactor, sm2.consecutiveCorrect, sm2.nextReviewAt);\n\n updateMastery(db, userId, question.taskStatement, question.domainId, result.isCorrect, sm2.consecutiveCorrect);\n\n const followUpOptions: readonly FollowUpOption[] = result.isCorrect\n ? [\n { key: 'next', label: 'Next question' },\n { key: 'why_wrong', label: 'Explain why the others are wrong' },\n ] as const\n : [\n { key: 'next', label: 'Got it, next question' },\n { key: 'code_example', label: 'Explain with a code example' },\n { key: 'concept', label: 'Show me the concept lesson' },\n { key: 'handout', label: 'Show me the handout' },\n { key: 'project', label: 'Show me in the reference project' },\n ] as const;\n\n const elicitOptions = followUpOptions.map((opt) => ({\n value: opt.key,\n title: opt.label,\n }));\n\n const elicitMessage = result.isCorrect\n ? 'Nice work! What would you like to do next?'\n : 'What would you like to do next?';\n\n const selectedFollowUp = await elicitSingleSelect(\n server,\n elicitMessage,\n 'followUp',\n elicitOptions,\n );\n\n const response = {\n questionId: result.questionId,\n isCorrect: result.isCorrect,\n correctAnswer: result.correctAnswer,\n explanation: result.explanation,\n whyYourAnswerWasWrong: result.whyUserWasWrong,\n references: result.references,\n followUpOptions,\n ...(selectedFollowUp != null ? { selectedFollowUp } : {}),\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n\nexport interface ElicitOption {\n readonly value: string;\n readonly title: string;\n}\n\n/**\n * Elicit a single selection from the user via radio buttons.\n * Falls back gracefully if the client doesn't support elicitation.\n */\nexport async function elicitSingleSelect(\n mcpServer: McpServer,\n message: string,\n fieldName: string,\n options: readonly ElicitOption[],\n): Promise<string | null> {\n try {\n const result = await mcpServer.server.elicitInput({\n mode: 'form',\n message,\n requestedSchema: {\n type: 'object',\n properties: {\n [fieldName]: {\n type: 'string',\n title: fieldName,\n oneOf: options.map(o => ({ const: o.value, title: o.title })),\n },\n },\n required: [fieldName],\n },\n });\n\n if (result.action === 'accept' && result.content) {\n return result.content[fieldName] as string;\n }\n return null;\n } catch (err) {\n // Client doesn't support elicitation — return null to fall back to text\n console.error('[connectry-architect] elicitation failed:', err instanceof Error ? err.message : String(err));\n return null;\n }\n}\n","import type { Question, GradeResult, AnswerOption } from '../types.js';\n\nexport function gradeAnswer(question: Question, userAnswer: string): GradeResult {\n const normalizedAnswer = userAnswer.toUpperCase() as AnswerOption;\n const isCorrect = normalizedAnswer === question.correctAnswer;\n return {\n questionId: question.id, isCorrect, userAnswer: normalizedAnswer,\n correctAnswer: question.correctAnswer, explanation: question.explanation,\n whyUserWasWrong: isCorrect ? null : (question.whyWrongMap[normalizedAnswer] ?? null),\n references: question.references,\n };\n}\n","import type { SM2Result } from '../types.js';\n\ninterface SM2Input {\n readonly isCorrect: boolean;\n readonly previousInterval: number;\n readonly previousEaseFactor: number;\n readonly previousConsecutiveCorrect: number;\n}\n\nexport function calculateSM2(input: SM2Input): SM2Result {\n const { isCorrect, previousInterval, previousEaseFactor, previousConsecutiveCorrect } = input;\n if (!isCorrect) {\n const newEase = Math.max(1.3, previousEaseFactor - 0.2);\n const nextReviewAt = addDays(new Date(), 1);\n return { interval: 1, easeFactor: Math.round(newEase * 100) / 100, consecutiveCorrect: 0, nextReviewAt: nextReviewAt.toISOString() };\n }\n const newConsecutive = previousConsecutiveCorrect + 1;\n const newEase = Math.max(1.3, previousEaseFactor + 0.1);\n let interval: number;\n if (newConsecutive === 1) interval = 1;\n else if (newConsecutive === 2) interval = 3;\n else interval = Math.round(previousInterval * previousEaseFactor);\n const nextReviewAt = addDays(new Date(), interval);\n return { interval, easeFactor: Math.round(newEase * 100) / 100, consecutiveCorrect: newConsecutive, nextReviewAt: nextReviewAt.toISOString() };\n}\n\nfunction addDays(date: Date, days: number): Date {\n const result = new Date(date);\n result.setDate(result.getDate() + days);\n return result;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Curriculum, Question, QuestionBank } from '../types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n// In bundled mode, __dirname is dist/. Data files are at dist/data/.\n// In dev mode, __dirname is src/data/. Data files are in the same directory.\nconst DATA_DIR = fs.existsSync(path.join(__dirname, 'data', 'curriculum.json'))\n ? path.join(__dirname, 'data')\n : __dirname;\n\nlet cachedCurriculum: Curriculum | null = null;\nlet cachedQuestions: ReadonlyMap<number, readonly Question[]> | null = null;\n\nexport function loadCurriculum(): Curriculum {\n if (cachedCurriculum) return cachedCurriculum;\n const raw = fs.readFileSync(path.join(DATA_DIR, 'curriculum.json'), 'utf-8');\n cachedCurriculum = JSON.parse(raw) as Curriculum;\n return cachedCurriculum;\n}\n\nexport function loadQuestions(domainId?: number): readonly Question[] {\n if (!cachedQuestions) {\n const questionsMap = new Map<number, readonly Question[]>();\n for (let d = 1; d <= 5; d++) {\n const filePath = path.join(DATA_DIR, 'questions', `domain-${d}.json`);\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, 'utf-8');\n const bank = JSON.parse(raw) as QuestionBank;\n questionsMap.set(d, bank.questions);\n } else {\n questionsMap.set(d, []);\n }\n }\n cachedQuestions = questionsMap;\n }\n if (domainId !== undefined) return cachedQuestions.get(domainId) ?? [];\n return Array.from(cachedQuestions.values()).flat();\n}\n\nexport function loadHandout(taskStatement: string): string | null {\n const filename = getHandoutFilename(taskStatement);\n const filePath = path.join(DATA_DIR, 'handouts', filename);\n if (!fs.existsSync(filePath)) return null;\n return fs.readFileSync(filePath, 'utf-8');\n}\n\nfunction getHandoutFilename(taskStatement: string): string {\n const curriculum = loadCurriculum();\n for (const domain of curriculum.domains) {\n for (const ts of domain.taskStatements) {\n if (ts.id === taskStatement) {\n const slug = ts.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/-+$/, '');\n return `${ts.id}-${slug}.md`;\n }\n }\n }\n return `${taskStatement}.md`;\n}\n","import type Database from 'better-sqlite3';\nimport type { AnswerRecord } from '../types.js';\n\nexport function recordAnswer(\n db: Database.Database, userId: string, questionId: string, taskStatement: string,\n domainId: number, userAnswer: string, correctAnswer: string, isCorrect: boolean, difficulty: string\n): void {\n db.prepare(`\n INSERT INTO answers (userId, questionId, taskStatement, domainId, userAnswer, correctAnswer, isCorrect, difficulty)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(userId, questionId, taskStatement, domainId, userAnswer, correctAnswer, isCorrect ? 1 : 0, difficulty);\n}\n\nexport function getRecentAnswers(db: Database.Database, userId: string, limit: number = 50): readonly AnswerRecord[] {\n return db.prepare('SELECT * FROM answers WHERE userId = ? ORDER BY answeredAt DESC LIMIT ?').all(userId, limit) as AnswerRecord[];\n}\n\nexport function getAnswersByTaskStatement(db: Database.Database, userId: string, taskStatement: string): readonly AnswerRecord[] {\n return db.prepare('SELECT * FROM answers WHERE userId = ? AND taskStatement = ? ORDER BY answeredAt DESC').all(userId, taskStatement) as AnswerRecord[];\n}\n\nexport function getAnsweredQuestionIds(db: Database.Database, userId: string): Set<string> {\n const rows = db.prepare('SELECT DISTINCT questionId FROM answers WHERE userId = ?').all(userId) as Array<{ questionId: string }>;\n return new Set(rows.map(r => r.questionId));\n}\n\nexport function getTotalStats(db: Database.Database, userId: string): { total: number; correct: number } {\n const row = db.prepare('SELECT COUNT(*) as total, SUM(CASE WHEN isCorrect THEN 1 ELSE 0 END) as correct FROM answers WHERE userId = ?').get(userId) as { total: number; correct: number };\n return { total: row.total, correct: row.correct ?? 0 };\n}\n","import type Database from 'better-sqlite3';\nimport type { DomainMastery, MasteryLevel } from '../types.js';\n\nexport function getMastery(db: Database.Database, userId: string, taskStatement: string): DomainMastery | undefined {\n return db.prepare('SELECT * FROM domain_mastery WHERE userId = ? AND taskStatement = ?').get(userId, taskStatement) as DomainMastery | undefined;\n}\n\nexport function getAllMastery(db: Database.Database, userId: string): readonly DomainMastery[] {\n return db.prepare('SELECT * FROM domain_mastery WHERE userId = ? ORDER BY domainId, taskStatement').all(userId) as DomainMastery[];\n}\n\nexport function getWeakAreas(db: Database.Database, userId: string, threshold: number = 70): readonly DomainMastery[] {\n return db.prepare('SELECT * FROM domain_mastery WHERE userId = ? AND accuracyPercent < ? AND totalAttempts > 0 ORDER BY accuracyPercent ASC').all(userId, threshold) as DomainMastery[];\n}\n\nfunction calculateMasteryLevel(accuracy: number, total: number, consecutiveCorrect: number): MasteryLevel {\n if (total === 0) return 'unassessed';\n if (accuracy >= 90 && total >= 5 && consecutiveCorrect >= 3) return 'mastered';\n if (accuracy >= 70) return 'strong';\n if (accuracy >= 50) return 'developing';\n return 'weak';\n}\n\nexport function updateMastery(\n db: Database.Database, userId: string, taskStatement: string, domainId: number, isCorrect: boolean, consecutiveCorrect: number\n): DomainMastery {\n const existing = getMastery(db, userId, taskStatement);\n if (!existing) {\n const accuracy = isCorrect ? 100 : 0;\n const level = calculateMasteryLevel(accuracy, 1, isCorrect ? 1 : 0);\n db.prepare(`INSERT INTO domain_mastery (userId, taskStatement, domainId, totalAttempts, correctAttempts, accuracyPercent, masteryLevel, lastTestedAt) VALUES (?, ?, ?, 1, ?, ?, ?, CURRENT_TIMESTAMP)`).run(userId, taskStatement, domainId, isCorrect ? 1 : 0, accuracy, level);\n } else {\n const newTotal = existing.totalAttempts + 1;\n const newCorrect = existing.correctAttempts + (isCorrect ? 1 : 0);\n const accuracy = Math.round((newCorrect / newTotal) * 100);\n const level = calculateMasteryLevel(accuracy, newTotal, consecutiveCorrect);\n db.prepare(`UPDATE domain_mastery SET totalAttempts = ?, correctAttempts = ?, accuracyPercent = ?, masteryLevel = ?, lastTestedAt = CURRENT_TIMESTAMP WHERE userId = ? AND taskStatement = ?`).run(newTotal, newCorrect, accuracy, level, userId, taskStatement);\n }\n return getMastery(db, userId, taskStatement)!;\n}\n","import type Database from 'better-sqlite3';\nimport type { ReviewScheduleEntry } from '../types.js';\n\nexport function getReviewSchedule(db: Database.Database, userId: string, taskStatement: string): ReviewScheduleEntry | undefined {\n return db.prepare('SELECT * FROM review_schedule WHERE userId = ? AND taskStatement = ?').get(userId, taskStatement) as ReviewScheduleEntry | undefined;\n}\n\nexport function getOverdueReviews(db: Database.Database, userId: string): readonly ReviewScheduleEntry[] {\n return db.prepare('SELECT * FROM review_schedule WHERE userId = ? AND nextReviewAt <= CURRENT_TIMESTAMP ORDER BY nextReviewAt ASC').all(userId) as ReviewScheduleEntry[];\n}\n\nexport function upsertReviewSchedule(\n db: Database.Database, userId: string, taskStatement: string, interval: number, easeFactor: number, consecutiveCorrect: number, nextReviewAt: string\n): void {\n db.prepare(`\n INSERT INTO review_schedule (userId, taskStatement, nextReviewAt, interval, easeFactor, consecutiveCorrect) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(userId, taskStatement) DO UPDATE SET nextReviewAt = excluded.nextReviewAt, interval = excluded.interval, easeFactor = excluded.easeFactor, consecutiveCorrect = excluded.consecutiveCorrect\n `).run(userId, taskStatement, nextReviewAt, interval, easeFactor, consecutiveCorrect);\n}\n","import type Database from 'better-sqlite3';\nimport type { User } from '../types.js';\n\nexport function ensureUser(db: Database.Database, userId: string): User {\n const existing = db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as User | undefined;\n if (existing) {\n db.prepare('UPDATE users SET lastActivityAt = CURRENT_TIMESTAMP WHERE id = ?').run(userId);\n return { ...existing, lastActivityAt: new Date().toISOString() };\n }\n db.prepare(\n 'INSERT INTO users (id, createdAt, lastActivityAt) VALUES (?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)'\n ).run(userId);\n return db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as User;\n}\n\nexport function updateLearningPath(db: Database.Database, userId: string, path: string): void {\n db.prepare('UPDATE users SET learningPath = ?, assessmentCompleted = TRUE WHERE id = ?').run(path, userId);\n}\n\nexport function getUser(db: Database.Database, userId: string): User | undefined {\n return db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as User | undefined;\n}\n","export const QUIZ_WIDGET_URI = 'ui://connectry-architect/quiz';\n\nexport function buildQuizMeta(): {\n readonly 'ui/resourceUri': string;\n readonly ui: { readonly resourceUri: string };\n} {\n return {\n 'ui/resourceUri': QUIZ_WIDGET_URI,\n ui: { resourceUri: QUIZ_WIDGET_URI },\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getAllMastery } from '../db/mastery.js';\nimport { getTotalStats } from '../db/answers.js';\nimport { getOverdueReviews } from '../db/review-schedule.js';\nimport { loadCurriculum } from '../data/loader.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetProgress(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_progress',\n 'Get your certification study progress overview including mastery levels, accuracy, and review status.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n const mastery = getAllMastery(db, userId);\n const stats = getTotalStats(db, userId);\n const overdueReviews = getOverdueReviews(db, userId);\n\n const domainProgress = curriculum.domains.map(d => {\n const domainMastery = mastery.filter(m => m.domainId === d.id);\n const avgAccuracy = domainMastery.length > 0\n ? Math.round(domainMastery.reduce((sum, m) => sum + m.accuracyPercent, 0) / domainMastery.length)\n : 0;\n const masteredCount = domainMastery.filter(m => m.masteryLevel === 'mastered').length;\n return ` D${d.id}: ${d.title} — ${avgAccuracy}% accuracy, ${masteredCount}/${d.taskStatements.length} mastered`;\n });\n\n const overallAccuracy = stats.total > 0 ? Math.round((stats.correct / stats.total) * 100) : 0;\n\n const text = [\n '═══ CERTIFICATION STUDY PROGRESS ═══',\n '',\n `Questions Answered: ${stats.total}`,\n `Overall Accuracy: ${overallAccuracy}%`,\n `Reviews Due: ${overdueReviews.length}`,\n '',\n 'Domain Progress:',\n ...domainProgress,\n ].join('\\n');\n\n return { content: [{ type: 'text' as const, text }] };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadCurriculum } from '../data/loader.js';\nimport { getAllMastery } from '../db/mastery.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetCurriculum(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_curriculum',\n 'View the full certification curriculum with domains, task statements, and your current mastery for each.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n const mastery = getAllMastery(db, userId);\n\n const lines: string[] = ['═══ CERTIFICATION CURRICULUM ═══', ''];\n for (const domain of curriculum.domains) {\n lines.push(`## Domain ${domain.id}: ${domain.title} (${domain.weight}%)`);\n lines.push('');\n for (const ts of domain.taskStatements) {\n const m = mastery.find(x => x.taskStatement === ts.id);\n const level = m ? m.masteryLevel : 'unassessed';\n const acc = m ? `${m.accuracyPercent}%` : '—';\n lines.push(` ${ts.id} [${level.toUpperCase()}] ${ts.title} (${acc})`);\n }\n lines.push('');\n }\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadCurriculum, loadHandout } from '../data/loader.js';\nimport { getMastery } from '../db/mastery.js';\nimport { getAnswersByTaskStatement } from '../db/answers.js';\nimport { hasViewedHandout } from '../db/handout-views.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetSectionDetails(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_section_details',\n 'Get detailed information about a specific task statement including concept lesson, mastery, and history.',\n { taskStatement: z.string().describe('Task statement ID, e.g. \"1.1\"') },\n async ({ taskStatement }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n let found = null;\n for (const d of curriculum.domains) {\n for (const ts of d.taskStatements) {\n if (ts.id === taskStatement) { found = { domain: d, ts }; break; }\n }\n if (found) break;\n }\n if (!found) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Task statement not found', taskStatement }) }],\n isError: true,\n };\n }\n const mastery = getMastery(db, userId, taskStatement);\n const answers = getAnswersByTaskStatement(db, userId, taskStatement);\n const handoutViewed = hasViewedHandout(db, userId, taskStatement);\n const handout = loadHandout(taskStatement);\n\n const lines: string[] = [\n `═══ ${found.ts.id}: ${found.ts.title} ═══`,\n `Domain: ${found.domain.title}`,\n `Description: ${found.ts.description}`,\n '',\n `Mastery: ${mastery?.masteryLevel ?? 'unassessed'}`,\n `Accuracy: ${mastery?.accuracyPercent ?? 0}%`,\n `Attempts: ${mastery?.totalAttempts ?? 0}`,\n `Handout Viewed: ${handoutViewed ? 'Yes' : 'No'}`,\n '',\n ];\n if (handout) {\n lines.push('--- Concept Lesson ---', '', handout);\n }\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import type Database from 'better-sqlite3';\n\nexport function recordHandoutView(db: Database.Database, userId: string, taskStatement: string): void {\n db.prepare(`INSERT INTO handout_views (userId, taskStatement) VALUES (?, ?) ON CONFLICT(userId, taskStatement) DO UPDATE SET viewedAt = CURRENT_TIMESTAMP`).run(userId, taskStatement);\n}\n\nexport function hasViewedHandout(db: Database.Database, userId: string, taskStatement: string): boolean {\n const row = db.prepare('SELECT 1 FROM handout_views WHERE userId = ? AND taskStatement = ?').get(userId, taskStatement);\n return row !== undefined;\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { selectNextQuestion } from '../engine/question-selector.js';\nimport { getAnsweredQuestionIds } from '../db/answers.js';\nimport { getOverdueReviews } from '../db/review-schedule.js';\nimport { getWeakAreas } from '../db/mastery.js';\nimport { ensureUser } from '../db/users.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nconst OPTION_KEYS = ['A', 'B', 'C', 'D'] as const;\n\nfunction formatQuestionText(question: {\n readonly id: string;\n readonly taskStatement: string;\n readonly domainId: number;\n readonly difficulty: string;\n readonly scenario: string;\n readonly text: string;\n readonly options: { readonly A: string; readonly B: string; readonly C: string; readonly D: string };\n}): string {\n const lines = [\n `**Question ${question.id}** (Domain ${question.domainId} | ${question.difficulty})`,\n '',\n `**Task:** ${question.taskStatement}`,\n '',\n '---',\n '',\n question.scenario,\n '',\n `**${question.text}**`,\n '',\n ...OPTION_KEYS.map(key => ` **${key}.** ${question.options[key]}`),\n ];\n return lines.join('\\n');\n}\n\nexport function registerGetPracticeQuestion(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_practice_question',\n 'Get the next practice question based on your learning progress. Prioritizes review questions, then weak areas, then new material.',\n {\n domainId: z.number().optional().describe('Optional domain ID to filter questions (1-5)'),\n difficulty: z.enum(['easy', 'medium', 'hard']).optional().describe('Optional difficulty filter'),\n },\n async ({ domainId, difficulty }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const answeredIds = getAnsweredQuestionIds(db, userId);\n const overdueReviews = getOverdueReviews(db, userId);\n const weakAreas = getWeakAreas(db, userId);\n let questions = loadQuestions(domainId);\n if (difficulty) {\n questions = questions.filter(q => q.difficulty === difficulty);\n }\n const question = selectNextQuestion(questions, overdueReviews, weakAreas, answeredIds);\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: 'No more questions available for the selected criteria. Try a different domain or difficulty.' }],\n };\n }\n\n const questionText = formatQuestionText(question);\n\n const elicitOptions = OPTION_KEYS.map(key => ({\n value: key,\n title: `${key}. ${question.options[key]}`,\n }));\n\n const selectedAnswer = await elicitSingleSelect(\n server,\n questionText,\n 'answer',\n elicitOptions,\n );\n\n if (selectedAnswer) {\n const responseText = [\n questionText,\n '',\n '---',\n '',\n `**Selected answer: ${selectedAnswer}**`,\n '',\n `Use submit_answer with questionId \"${question.id}\" and answer \"${selectedAnswer}\" to grade this response.`,\n ].join('\\n');\n\n return {\n content: [{ type: 'text' as const, text: responseText }],\n _meta: buildQuizMeta(),\n };\n }\n\n const fallbackText = [\n questionText,\n '',\n '---',\n '',\n `Question ID: ${question.id}`,\n '',\n 'Use submit_answer with the question ID and your chosen answer (A, B, C, or D) to check your response.',\n ].join('\\n');\n\n return {\n content: [{ type: 'text' as const, text: fallbackText }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import type { Question, ReviewScheduleEntry, DomainMastery } from '../types.js';\n\nexport function selectNextQuestion(\n allQuestions: readonly Question[], overdueReviews: readonly ReviewScheduleEntry[],\n weakAreas: readonly DomainMastery[], answeredQuestionIds: ReadonlySet<string>,\n): Question | undefined {\n if (overdueReviews.length > 0) {\n const weakestFirst = [...overdueReviews].sort((a, b) => a.easeFactor - b.easeFactor);\n for (const review of weakestFirst) {\n const question = findUnansweredForTaskStatement(allQuestions, review.taskStatement, answeredQuestionIds);\n if (question) return question;\n }\n }\n if (weakAreas.length > 0) {\n for (const area of weakAreas) {\n const question = findUnansweredForTaskStatement(allQuestions, area.taskStatement, answeredQuestionIds);\n if (question) return question;\n }\n }\n return allQuestions.find((q) => !answeredQuestionIds.has(q.id));\n}\n\nfunction findUnansweredForTaskStatement(\n questions: readonly Question[], taskStatement: string, answeredIds: ReadonlySet<string>,\n): Question | undefined {\n return questions.find((q) => q.taskStatement === taskStatement && !answeredIds.has(q.id));\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, Question } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { ensureUser } from '../db/users.js';\nimport { elicitSingleSelect } from './elicit.js';\n\nconst OPTION_KEYS = ['A', 'B', 'C', 'D'] as const;\n\nfunction buildAssessmentQuestions(): readonly Question[] {\n const questions: Question[] = [];\n for (let d = 1; d <= 5; d++) {\n const domainQuestions = loadQuestions(d);\n const easy = domainQuestions.find(q => q.difficulty === 'easy');\n const medium = domainQuestions.find(q => q.difficulty === 'medium');\n const hard = domainQuestions.find(q => q.difficulty === 'hard');\n if (easy) questions.push(easy);\n if (medium) questions.push(medium);\n if (hard) questions.push(hard);\n }\n return questions;\n}\n\nfunction formatQuestion(question: Question, index: number, total: number): string {\n const domainNames: Record<number, string> = {\n 1: 'Agentic Architecture',\n 2: 'Tool Design & MCP',\n 3: 'Claude Code Config',\n 4: 'Prompt Engineering',\n 5: 'Context & Reliability',\n };\n const lines = [\n `**Assessment Question ${index + 1} of ${total}**`,\n `Domain ${question.domainId}: ${domainNames[question.domainId] ?? 'Unknown'} | ${question.difficulty}`,\n '',\n '---',\n '',\n question.scenario,\n '',\n `**${question.text}**`,\n '',\n ...OPTION_KEYS.map(key => ` **${key}.** ${question.options[key]}`),\n ];\n return lines.join('\\n');\n}\n\nexport function registerStartAssessment(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'start_assessment',\n 'Start the initial assessment. Returns ONE question at a time. After submitting the answer with submit_answer, call start_assessment again to get the next question. Repeats for all 15 questions (3 per domain).',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n const questions = buildAssessmentQuestions();\n if (questions.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No assessment questions available.' }],\n };\n }\n\n // Check how many assessment questions have been answered\n const answeredIds = db.prepare(\n `SELECT questionId FROM answers WHERE userId = ? AND questionId IN (${questions.map(() => '?').join(',')})`,\n ).all(userId, ...questions.map(q => q.id)) as readonly { questionId: string }[];\n\n const answeredSet = new Set(answeredIds.map(r => r.questionId));\n const nextQuestion = questions.find(q => !answeredSet.has(q.id));\n\n // All done — compute results\n if (!nextQuestion) {\n const results = db.prepare(\n `SELECT domainId, COUNT(*) as total, SUM(CASE WHEN isCorrect THEN 1 ELSE 0 END) as correct\n FROM answers WHERE userId = ? AND questionId IN (${questions.map(() => '?').join(',')})\n GROUP BY domainId`,\n ).all(userId, ...questions.map(q => q.id)) as readonly { domainId: number; total: number; correct: number }[];\n\n const totalCorrect = results.reduce((sum, r) => sum + r.correct, 0);\n const totalQuestions = results.reduce((sum, r) => sum + r.total, 0);\n const overallAccuracy = totalQuestions > 0 ? Math.round((totalCorrect / totalQuestions) * 100) : 0;\n const path = overallAccuracy >= 60 ? 'exam-weighted' : 'beginner-friendly';\n\n db.prepare('UPDATE users SET assessmentCompleted = TRUE, learningPath = ? WHERE id = ?').run(path, userId);\n\n const domainNames: Record<number, string> = {\n 1: 'Agentic Architecture',\n 2: 'Tool Design & MCP',\n 3: 'Claude Code Config',\n 4: 'Prompt Engineering',\n 5: 'Context & Reliability',\n };\n\n const lines = [\n '**Assessment Complete!**',\n '',\n `Overall: ${totalCorrect}/${totalQuestions} (${overallAccuracy}%)`,\n `Learning path: **${path === 'exam-weighted' ? 'Exam-Weighted' : 'Beginner-Friendly'}**`,\n '',\n '**Per-domain results:**',\n '',\n ...results.map(r => ` D${r.domainId} ${domainNames[r.domainId] ?? ''}: ${r.correct}/${r.total} (${Math.round((r.correct / r.total) * 100)}%)`),\n '',\n '---',\n '',\n 'Use get_study_plan to get your personalized study recommendations, or get_practice_question to start practicing.',\n ];\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n };\n }\n\n // Serve next question\n const questionIndex = answeredSet.size;\n const questionText = formatQuestion(nextQuestion, questionIndex, questions.length);\n\n // Try elicitation for interactive selection\n const elicitOptions = OPTION_KEYS.map(key => ({\n value: key,\n title: `${key}. ${nextQuestion.options[key]}`,\n }));\n\n const selected = await elicitSingleSelect(\n server,\n questionText,\n 'answer',\n elicitOptions,\n );\n\n if (selected) {\n return {\n content: [{\n type: 'text' as const,\n text: [\n questionText,\n '',\n '---',\n '',\n `**Selected: ${selected}**`,\n '',\n `Submit this answer with submit_answer using questionId \"${nextQuestion.id}\" and answer \"${selected}\". Then call start_assessment again for the next question.`,\n ].join('\\n'),\n }],\n };\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: [\n questionText,\n '',\n '---',\n '',\n `Question ID: ${nextQuestion.id}`,\n '',\n 'Submit your answer (A, B, C, or D) with submit_answer, then call start_assessment again for the next question.',\n ].join('\\n'),\n }],\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getWeakAreas } from '../db/mastery.js';\nimport { loadCurriculum } from '../data/loader.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetWeakAreas(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_weak_areas',\n 'Identify your weakest task statements based on accuracy below 70%. Focus your study on these areas.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const curriculum = loadCurriculum();\n const weakAreas = getWeakAreas(db, userId);\n\n if (weakAreas.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No weak areas identified yet. Complete some questions first or all areas are above 70%!' }],\n };\n }\n\n const lines = ['═══ WEAK AREAS ═══', ''];\n for (const area of weakAreas) {\n const domain = curriculum.domains.find(d => d.id === area.domainId);\n const ts = domain?.taskStatements.find(t => t.id === area.taskStatement);\n lines.push(` ${area.taskStatement}: ${ts?.title ?? 'Unknown'}`);\n lines.push(` Accuracy: ${area.accuracyPercent}% (${area.correctAttempts}/${area.totalAttempts})`);\n lines.push(` Mastery: ${area.masteryLevel}`);\n lines.push('');\n }\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import type { DomainMastery, LearningPath } from '../types.js';\n\nconst BEGINNER_ORDER = [3, 4, 2, 1, 5];\nconst EXAM_WEIGHTED_ORDER = [1, 3, 4, 2, 5];\n\nexport function recommendPath(assessmentAccuracy: number): LearningPath {\n return assessmentAccuracy >= 60 ? 'exam-weighted' : 'beginner-friendly';\n}\n\nexport function getDomainOrder(path: LearningPath): readonly number[] {\n return path === 'beginner-friendly' ? BEGINNER_ORDER : EXAM_WEIGHTED_ORDER;\n}\n\nexport function getNextRecommendedDomain(path: LearningPath, masteryByDomain: ReadonlyMap<number, readonly DomainMastery[]>): number {\n const order = getDomainOrder(path);\n for (const domainId of order) {\n const masteries = masteryByDomain.get(domainId) ?? [];\n const avgAccuracy = masteries.length > 0 ? masteries.reduce((sum, m) => sum + m.accuracyPercent, 0) / masteries.length : 0;\n if (avgAccuracy < 70) return domainId;\n }\n let weakestDomain = order[0];\n let lowestAccuracy = 100;\n for (const domainId of order) {\n const masteries = masteryByDomain.get(domainId) ?? [];\n const avg = masteries.length > 0 ? masteries.reduce((sum, m) => sum + m.accuracyPercent, 0) / masteries.length : 0;\n if (avg < lowestAccuracy) { lowestAccuracy = avg; weakestDomain = domainId; }\n }\n return weakestDomain;\n}\n\nexport function estimateTimeRemaining(totalQuestions: number, answeredQuestions: number, avgSecondsPerQuestion: number = 45): string {\n const remaining = totalQuestions - answeredQuestions;\n const totalMinutes = Math.round((remaining * avgSecondsPerQuestion) / 60);\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n if (hours === 0) return `${minutes} minutes`;\n return `${hours} hours ${minutes} minutes`;\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getUser } from '../db/users.js';\nimport { getAllMastery } from '../db/mastery.js';\nimport { getOverdueReviews } from '../db/review-schedule.js';\nimport { getTotalStats } from '../db/answers.js';\nimport { loadCurriculum, loadQuestions } from '../data/loader.js';\nimport { getNextRecommendedDomain, getDomainOrder, estimateTimeRemaining } from '../engine/adaptive-path.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetStudyPlan(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_study_plan',\n 'Get a personalized study plan based on your assessment results, weak areas, and learning path.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const user = getUser(db, userId);\n const curriculum = loadCurriculum();\n const mastery = getAllMastery(db, userId);\n const overdueReviews = getOverdueReviews(db, userId);\n const stats = getTotalStats(db, userId);\n const allQuestions = loadQuestions();\n const path = user?.learningPath ?? 'beginner-friendly';\n\n const masteryByDomain = new Map<number, typeof mastery>();\n for (const m of mastery) {\n const existing = masteryByDomain.get(m.domainId) ?? [];\n masteryByDomain.set(m.domainId, [...existing, m]);\n }\n\n const nextDomain = getNextRecommendedDomain(path as any, masteryByDomain);\n const domainOrder = getDomainOrder(path as any);\n const timeEstimate = estimateTimeRemaining(allQuestions.length, stats.total);\n\n const domain = curriculum.domains.find(d => d.id === nextDomain);\n\n const lines = [\n '═══ YOUR STUDY PLAN ═══',\n '',\n `Learning Path: ${path}`,\n `Estimated Time Remaining: ${timeEstimate}`,\n '',\n `Next Recommended Domain: D${nextDomain} — ${domain?.title ?? 'Unknown'}`,\n '',\n 'Domain Study Order:',\n ...domainOrder.map((id, i) => {\n const d = curriculum.domains.find(x => x.id === id);\n return ` ${i + 1}. D${id}: ${d?.title ?? 'Unknown'}`;\n }),\n '',\n `Reviews Due: ${overdueReviews.length}`,\n overdueReviews.length > 0 ? 'Start with your overdue reviews before new material.' : '',\n ];\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PROJECTS_DIR = path.resolve(__dirname, '..', '..', 'projects');\n\nconst PROJECTS = [\n { id: 'capstone', name: 'Capstone — Multi-Agent Research System', domains: [1, 2, 3, 4, 5] },\n { id: 'd1-agentic', name: 'D1 Mini — Agentic Loop', domains: [1] },\n { id: 'd2-tools', name: 'D2 Mini — Tool Design', domains: [2] },\n { id: 'd3-config', name: 'D3 Mini — Claude Code Config', domains: [3] },\n { id: 'd4-prompts', name: 'D4 Mini — Prompt Engineering', domains: [4] },\n { id: 'd5-context', name: 'D5 Mini — Context Management', domains: [5] },\n] as const;\n\nfunction listFilesRecursive(dir: string, prefix = ''): readonly string[] {\n if (!fs.existsSync(dir)) return [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n return entries.flatMap((entry): readonly string[] => {\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n return listFilesRecursive(path.join(dir, entry.name), relativePath);\n }\n return [relativePath];\n });\n}\n\nexport function registerScaffoldProject(server: McpServer, _db: Database.Database, _userConfig: UserConfig): void {\n server.tool(\n 'scaffold_project',\n 'Get instructions for a reference project to practice certification concepts hands-on.',\n { projectId: z.string().optional().describe('Project ID (e.g. \"capstone\", \"d1-agentic\"). Omit to see available projects.') },\n async ({ projectId }) => {\n if (!projectId) {\n const lines = [\n '═══ REFERENCE PROJECTS ═══',\n '',\n ...PROJECTS.map(p => ` ${p.id}: ${p.name} (Domains: ${p.domains.join(', ')})`),\n ];\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n\n const project = PROJECTS.find(p => p.id === projectId);\n if (!project) {\n return {\n content: [{ type: 'text' as const, text: `Project \"${projectId}\" not found. Use scaffold_project without arguments to see available projects.` }],\n isError: true,\n };\n }\n\n const projectDir = path.join(PROJECTS_DIR, projectId);\n if (!fs.existsSync(projectDir)) {\n return {\n content: [{ type: 'text' as const, text: `Project directory for \"${project.name}\" not found. The project files may not be installed yet.` }],\n isError: true,\n };\n }\n\n const readmePath = path.join(projectDir, 'README.md');\n const readme = fs.existsSync(readmePath)\n ? fs.readFileSync(readmePath, 'utf-8')\n : null;\n\n const files = listFilesRecursive(projectDir);\n\n const sections = [\n `═══ ${project.name} ═══`,\n '',\n `Domains: ${project.domains.join(', ')}`,\n '',\n ];\n\n if (readme) {\n sections.push('--- README ---', '', readme, '');\n }\n\n sections.push(\n '--- Project Files ---',\n '',\n ...files.map(f => ` ${f}`),\n '',\n '--- Next Steps ---',\n '',\n 'Explore the project files above to understand the architecture.',\n 'Each file demonstrates certification concepts in practice.',\n `Project root: projects/${projectId}/`,\n );\n\n return {\n content: [{ type: 'text' as const, text: sections.join('\\n') }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\n\nexport function registerResetProgress(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'reset_progress',\n 'WARNING: Permanently deletes ALL your study progress including answers, mastery data, and review schedules. This cannot be undone.',\n { confirmed: z.boolean().describe('Must be true to confirm the reset') },\n async ({ confirmed }) => {\n if (!confirmed) {\n return { content: [{ type: 'text' as const, text: 'Reset cancelled. Your progress is safe.' }] };\n }\n const userId = userConfig.userId;\n db.prepare('DELETE FROM answers WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM domain_mastery WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM review_schedule WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM session_state WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM study_sessions WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM handout_views WHERE userId = ?').run(userId);\n db.prepare('DELETE FROM exam_attempts WHERE userId = ?').run(userId);\n\n return { content: [{ type: 'text' as const, text: 'All progress has been reset, including exam history. You can start fresh with start_assessment.' }] };\n }\n );\n}\n","import type { Question, DomainExamScore } from '../types.js';\n\n/** Domain weights matching the real exam, mapped to 60 questions */\nconst EXAM_DISTRIBUTION: ReadonlyArray<{ readonly domainId: number; readonly count: number }> = [\n { domainId: 1, count: 16 }, // 27%\n { domainId: 2, count: 11 }, // 18%\n { domainId: 3, count: 12 }, // 20%\n { domainId: 4, count: 12 }, // 20%\n { domainId: 5, count: 9 }, // 15%\n] as const;\n\nconst PASSING_SCORE = 720;\nconst TOTAL_SCALE = 1000;\n\n/**\n * Build a 60-question practice exam by randomly selecting from the question bank.\n * Avoids repeating questions from recent exams when possible.\n * Difficulty mix per domain: ~30% easy, ~40% medium, ~30% hard\n *\n * @param previouslyUsedIds - Question IDs from recent exams to avoid (best-effort)\n */\nexport function buildPracticeExam(\n allQuestions: readonly Question[],\n previouslyUsedIds: ReadonlySet<string> = new Set(),\n): readonly Question[] {\n const selected: Question[] = [];\n\n for (const { domainId, count } of EXAM_DISTRIBUTION) {\n const domainQuestions = allQuestions.filter(q => q.domainId === domainId);\n\n // Prefer questions NOT used in recent exams\n const fresh = domainQuestions.filter(q => !previouslyUsedIds.has(q.id));\n const pool = fresh.length >= count ? fresh : domainQuestions;\n\n const easy = shuffleArray(pool.filter(q => q.difficulty === 'easy'));\n const medium = shuffleArray(pool.filter(q => q.difficulty === 'medium'));\n const hard = shuffleArray(pool.filter(q => q.difficulty === 'hard'));\n\n const easyCount = Math.round(count * 0.3);\n const hardCount = Math.round(count * 0.3);\n const mediumCount = count - easyCount - hardCount;\n\n const pick = [\n ...easy.slice(0, easyCount),\n ...medium.slice(0, mediumCount),\n ...hard.slice(0, hardCount),\n ];\n\n // If we don't have enough of a difficulty, fill from others\n if (pick.length < count) {\n const remaining = shuffleArray(\n pool.filter(q => !pick.some(p => p.id === q.id))\n );\n pick.push(...remaining.slice(0, count - pick.length));\n }\n\n selected.push(...pick.slice(0, count));\n }\n\n return shuffleArray(selected);\n}\n\n/** Build initial domain scores map for a new exam */\nexport function buildInitialDomainScores(\n questions: readonly Question[],\n domainTitles: ReadonlyMap<number, string>,\n): Record<string, DomainExamScore> {\n const scores: Record<string, DomainExamScore> = {};\n\n for (const { domainId, count } of EXAM_DISTRIBUTION) {\n scores[`d${domainId}`] = {\n domainId,\n domainTitle: domainTitles.get(domainId) ?? `Domain ${domainId}`,\n totalQuestions: count,\n correctAnswers: 0,\n accuracyPercent: 0,\n weight: getWeight(domainId),\n };\n }\n\n return scores;\n}\n\nexport function calculateExamScore(correctAnswers: number, totalQuestions: number): number {\n return Math.round((correctAnswers / totalQuestions) * TOTAL_SCALE);\n}\n\nexport function isPassingScore(score: number): boolean {\n return score >= PASSING_SCORE;\n}\n\nexport { EXAM_DISTRIBUTION, PASSING_SCORE, TOTAL_SCALE };\n\nfunction getWeight(domainId: number): number {\n const weights: Record<number, number> = { 1: 27, 2: 18, 3: 20, 4: 20, 5: 15 };\n return weights[domainId] ?? 0;\n}\n\nfunction shuffleArray<T>(arr: readonly T[]): T[] {\n const shuffled = [...arr];\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];\n }\n return shuffled;\n}\n","import type Database from 'better-sqlite3';\nimport type { ExamAttempt, DomainExamScore } from '../types.js';\n\nexport function createExamAttempt(\n db: Database.Database,\n userId: string,\n questionIds: readonly string[],\n): number {\n const stmt = db.prepare(\n 'INSERT INTO exam_attempts (userId, totalQuestions, questionIds) VALUES (?, ?, ?)'\n );\n const result = stmt.run(userId, questionIds.length, JSON.stringify(questionIds));\n return Number(result.lastInsertRowid);\n}\n\nexport function getActiveExam(db: Database.Database, userId: string): ExamAttempt | null {\n const row = db.prepare(\n 'SELECT * FROM exam_attempts WHERE userId = ? AND completedAt IS NULL ORDER BY startedAt DESC LIMIT 1'\n ).get(userId) as Record<string, unknown> | undefined;\n return row ? rowToExamAttempt(row) : null;\n}\n\nexport function getExamById(db: Database.Database, examId: number): ExamAttempt | null {\n const row = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(examId) as Record<string, unknown> | undefined;\n return row ? rowToExamAttempt(row) : null;\n}\n\nexport function recordExamAnswer(\n db: Database.Database,\n examId: number,\n questionId: string,\n isCorrect: boolean,\n domainId: number,\n): void {\n const row = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(examId) as Record<string, unknown> | undefined;\n if (!row) return;\n\n const answeredIds: string[] = JSON.parse(row.answeredQuestionIds as string);\n const updatedAnswered = [...answeredIds, questionId];\n const newCorrect = (row.correctAnswers as number) + (isCorrect ? 1 : 0);\n\n const domainScores: Record<string, DomainExamScore> = JSON.parse(row.domainScores as string);\n const domainKey = `d${domainId}`;\n const existing = domainScores[domainKey];\n if (existing) {\n const updatedCorrect = existing.correctAnswers + (isCorrect ? 1 : 0);\n const updatedTotal = existing.totalQuestions;\n domainScores[domainKey] = {\n ...existing,\n correctAnswers: updatedCorrect,\n accuracyPercent: Math.round((updatedCorrect / updatedTotal) * 100),\n };\n }\n\n db.prepare(\n 'UPDATE exam_attempts SET correctAnswers = ?, answeredQuestionIds = ?, domainScores = ? WHERE id = ?'\n ).run(newCorrect, JSON.stringify(updatedAnswered), JSON.stringify(domainScores), examId);\n}\n\nexport function completeExam(db: Database.Database, examId: number): ExamAttempt | null {\n const row = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(examId) as Record<string, unknown> | undefined;\n if (!row) return null;\n\n const totalQuestions = row.totalQuestions as number;\n const correctAnswers = row.correctAnswers as number;\n const score = Math.round((correctAnswers / totalQuestions) * 1000);\n const passed = score >= 720;\n\n db.prepare(\n 'UPDATE exam_attempts SET completedAt = CURRENT_TIMESTAMP, score = ?, passed = ? WHERE id = ?'\n ).run(score, passed ? 1 : 0, examId);\n\n return getExamById(db, examId);\n}\n\nexport function getExamHistory(db: Database.Database, userId: string): readonly ExamAttempt[] {\n const rows = db.prepare(\n 'SELECT * FROM exam_attempts WHERE userId = ? AND completedAt IS NOT NULL ORDER BY completedAt DESC'\n ).all(userId) as Record<string, unknown>[];\n return rows.map(rowToExamAttempt);\n}\n\nfunction rowToExamAttempt(row: Record<string, unknown>): ExamAttempt {\n return {\n id: row.id as number,\n userId: row.userId as string,\n startedAt: row.startedAt as string,\n completedAt: (row.completedAt as string) ?? null,\n totalQuestions: row.totalQuestions as number,\n correctAnswers: row.correctAnswers as number,\n score: row.score as number,\n passed: Boolean(row.passed),\n questionIds: JSON.parse(row.questionIds as string),\n answeredQuestionIds: JSON.parse(row.answeredQuestionIds as string),\n domainScores: JSON.parse(row.domainScores as string),\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions, loadCurriculum } from '../data/loader.js';\nimport { buildPracticeExam, buildInitialDomainScores, EXAM_DISTRIBUTION } from '../engine/exam-builder.js';\nimport { createExamAttempt, getActiveExam, getExamHistory } from '../db/exam-attempts.js';\nimport { ensureUser } from '../db/users.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nexport function registerStartPracticeExam(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'start_practice_exam',\n 'Start a full 60-question practice exam simulating the real Claude Certified Architect — Foundations exam. Questions are weighted by domain (D1: 16, D2: 11, D3: 12, D4: 12, D5: 9). Scored out of 1000, passing is 720. Results are saved for comparison across attempts.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n // Check for active exam\n const active = getActiveExam(db, userId);\n if (active) {\n const remaining = active.totalQuestions - active.answeredQuestionIds.length;\n return {\n content: [{\n type: 'text' as const,\n text: [\n '═══ PRACTICE EXAM IN PROGRESS ═══',\n '',\n `You have an active practice exam (started ${active.startedAt}).`,\n `Progress: ${active.answeredQuestionIds.length}/${active.totalQuestions} questions answered`,\n `Remaining: ${remaining} questions`,\n '',\n 'Use get_practice_exam_question to continue, or ask to abandon this exam first.',\n ].join('\\n'),\n }],\n };\n }\n\n const allQuestions = loadQuestions();\n const curriculum = loadCurriculum();\n const domainTitles = new Map(curriculum.domains.map(d => [d.id, d.title]));\n\n // Gather question IDs from the most recent exam to avoid repetition\n const history = getExamHistory(db, userId);\n const recentIds = new Set(\n history.length > 0 ? history[0].questionIds : []\n );\n\n const examQuestions = buildPracticeExam(allQuestions, recentIds);\n const questionIds = examQuestions.map(q => q.id);\n const domainScores = buildInitialDomainScores(examQuestions, domainTitles);\n\n const examId = createExamAttempt(db, userId, questionIds);\n\n // Store domain scores\n db.prepare('UPDATE exam_attempts SET domainScores = ? WHERE id = ?')\n .run(JSON.stringify(domainScores), examId);\n\n const distribution = EXAM_DISTRIBUTION.map(({ domainId, count }) => {\n const title = domainTitles.get(domainId) ?? `Domain ${domainId}`;\n return ` D${domainId}: ${title} — ${count} questions (${domainScores[`d${domainId}`].weight}%)`;\n });\n\n const firstQuestion = examQuestions[0];\n\n const text = [\n '═══ PRACTICE EXAM STARTED ═══',\n '',\n 'Simulating the Claude Certified Architect — Foundations exam.',\n '',\n `Exam ID: ${examId}`,\n 'Total Questions: 60',\n 'Passing Score: 720/1000',\n '',\n 'Question Distribution:',\n ...distribution,\n '',\n '─── Question 1 of 60 ───',\n '',\n `Domain: D${firstQuestion.domainId}`,\n `Task: ${firstQuestion.taskStatement}`,\n `Difficulty: ${firstQuestion.difficulty}`,\n '',\n `Scenario: ${firstQuestion.scenario}`,\n '',\n firstQuestion.text,\n '',\n `A) ${firstQuestion.options.A}`,\n `B) ${firstQuestion.options.B}`,\n `C) ${firstQuestion.options.C}`,\n `D) ${firstQuestion.options.D}`,\n '',\n `[Submit your answer using submit_exam_answer with examId: ${examId} and questionId: \"${firstQuestion.id}\"]`,\n ].join('\\n');\n\n const selected = await elicitSingleSelect(server, 'Select your answer:', 'answer', [\n { value: 'A', title: `A) ${firstQuestion.options.A}` },\n { value: 'B', title: `B) ${firstQuestion.options.B}` },\n { value: 'C', title: `C) ${firstQuestion.options.C}` },\n { value: 'D', title: `D) ${firstQuestion.options.D}` },\n ]);\n\n const responseText = selected !== null\n ? `${text}\\n\\nUser selected: ${selected}`\n : text;\n\n return {\n content: [{\n type: 'text' as const,\n text: responseText,\n }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, Question } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { gradeAnswer } from '../engine/grading.js';\nimport { getExamById, recordExamAnswer, completeExam, getExamHistory } from '../db/exam-attempts.js';\nimport { ensureUser } from '../db/users.js';\nimport { elicitSingleSelect } from './elicit.js';\nimport { buildQuizMeta } from '../ui/meta.js';\n\nexport function registerSubmitExamAnswer(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'submit_exam_answer',\n 'Submit an answer for a practice exam question. The answer is graded deterministically. After all 60 questions, the exam is scored and saved. DO NOT soften results — relay the grading output verbatim.',\n {\n examId: z.number().describe('The practice exam ID'),\n questionId: z.string().describe('The question ID being answered'),\n answer: z.string().describe('Your answer: A, B, C, or D'),\n },\n async ({ examId, questionId, answer }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n const exam = getExamById(db, examId);\n if (!exam) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Exam not found', examId }) }],\n isError: true,\n };\n }\n if (exam.completedAt) {\n return {\n content: [{ type: 'text' as const, text: 'This exam is already completed. Start a new practice exam to try again.' }],\n isError: true,\n };\n }\n if (exam.answeredQuestionIds.includes(questionId)) {\n return {\n content: [{ type: 'text' as const, text: `Question ${questionId} has already been answered in this exam.` }],\n isError: true,\n };\n }\n\n const allQuestions = loadQuestions();\n const question = allQuestions.find(q => q.id === questionId);\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Question not found', questionId }) }],\n isError: true,\n };\n }\n\n // Grade the answer\n const result = gradeAnswer(question, answer);\n\n // Record in exam\n recordExamAnswer(db, examId, questionId, result.isCorrect, question.domainId);\n\n const answeredCount = exam.answeredQuestionIds.length + 1;\n const remaining = exam.totalQuestions - answeredCount;\n\n const lines: string[] = [];\n\n // Grade feedback\n if (result.isCorrect) {\n lines.push(`✅ Correct! (${answeredCount}/${exam.totalQuestions})`);\n } else {\n lines.push(`❌ Incorrect. The correct answer is ${result.correctAnswer}. (${answeredCount}/${exam.totalQuestions})`);\n if (result.whyUserWasWrong) {\n lines.push('', `Why ${result.userAnswer} is wrong: ${result.whyUserWasWrong}`);\n }\n }\n lines.push('', result.explanation);\n\n // Check if exam is complete\n if (remaining === 0) {\n const completed = completeExam(db, examId);\n if (completed) {\n lines.push('', '═══ PRACTICE EXAM COMPLETE ═══', '');\n lines.push(`Score: ${completed.score}/1000`);\n lines.push(`Result: ${completed.passed ? '✅ PASSED' : '❌ FAILED'} (passing: 720/1000)`);\n lines.push(`Correct: ${completed.correctAnswers}/${completed.totalQuestions}`);\n lines.push('');\n lines.push('Domain Breakdown:');\n\n const scores = completed.domainScores;\n for (const key of Object.keys(scores).sort()) {\n const ds = scores[key];\n lines.push(` D${ds.domainId}: ${ds.domainTitle} — ${ds.correctAnswers}/${ds.totalQuestions} (${ds.accuracyPercent}%) [weight: ${ds.weight}%]`);\n }\n\n // Compare with previous attempts\n const history = getExamHistory(db, userId);\n if (history.length > 1) {\n const previous = history[1]; // history[0] is current\n const scoreDiff = completed.score - previous.score;\n const arrow = scoreDiff > 0 ? '↑' : scoreDiff < 0 ? '↓' : '→';\n lines.push('');\n lines.push('─── Compared to Previous Attempt ───');\n lines.push(` Previous score: ${previous.score}/1000 ${previous.passed ? '(passed)' : '(failed)'}`);\n lines.push(` Change: ${arrow} ${scoreDiff > 0 ? '+' : ''}${scoreDiff} points`);\n\n // Per-domain comparison\n for (const key of Object.keys(scores).sort()) {\n const current = scores[key];\n const prev = previous.domainScores[key];\n if (prev) {\n const diff = current.accuracyPercent - prev.accuracyPercent;\n const dArrow = diff > 0 ? '↑' : diff < 0 ? '↓' : '→';\n lines.push(` D${current.domainId}: ${prev.accuracyPercent}% → ${current.accuracyPercent}% ${dArrow}`);\n }\n }\n }\n }\n } else {\n // Serve next question\n const nextQuestionId = exam.questionIds.find(\n id => !exam.answeredQuestionIds.includes(id) && id !== questionId\n );\n if (nextQuestionId) {\n const nextQuestion = allQuestions.find(q => q.id === nextQuestionId);\n if (nextQuestion) {\n lines.push('');\n lines.push(`─── Question ${answeredCount + 1} of ${exam.totalQuestions} ───`);\n lines.push('');\n lines.push(`Domain: D${nextQuestion.domainId}`);\n lines.push(`Task: ${nextQuestion.taskStatement}`);\n lines.push(`Difficulty: ${nextQuestion.difficulty}`);\n lines.push('');\n lines.push(`Scenario: ${nextQuestion.scenario}`);\n lines.push('');\n lines.push(nextQuestion.text);\n lines.push('');\n lines.push(`A) ${nextQuestion.options.A}`);\n lines.push(`B) ${nextQuestion.options.B}`);\n lines.push(`C) ${nextQuestion.options.C}`);\n lines.push(`D) ${nextQuestion.options.D}`);\n\n const selected = await elicitSingleSelect(server, 'Select your answer:', 'answer', [\n { value: 'A', title: `A) ${nextQuestion.options.A}` },\n { value: 'B', title: `B) ${nextQuestion.options.B}` },\n { value: 'C', title: `C) ${nextQuestion.options.C}` },\n { value: 'D', title: `D) ${nextQuestion.options.D}` },\n ]);\n\n if (selected !== null) {\n lines.push('', `User selected: ${selected}`);\n }\n }\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n _meta: buildQuizMeta(),\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { getExamHistory } from '../db/exam-attempts.js';\nimport { ensureUser } from '../db/users.js';\n\nexport function registerGetExamHistory(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'get_exam_history',\n 'View all completed practice exam attempts with scores, pass/fail status, and per-domain breakdowns. Compare your progress across attempts.',\n {},\n async () => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n const history = getExamHistory(db, userId);\n\n if (history.length === 0) {\n return {\n content: [{\n type: 'text' as const,\n text: [\n '═══ EXAM HISTORY ═══',\n '',\n 'No completed practice exams yet.',\n '',\n 'Use start_practice_exam to take your first 60-question practice exam.',\n 'Questions are weighted by domain — just like the real exam.',\n ].join('\\n'),\n }],\n };\n }\n\n const lines: string[] = [\n '═══ EXAM HISTORY ═══',\n '',\n `Total Attempts: ${history.length}`,\n `Best Score: ${Math.max(...history.map(h => h.score))}/1000`,\n `Latest Score: ${history[0].score}/1000`,\n '',\n ];\n\n for (const [i, attempt] of history.entries()) {\n const label = i === 0 ? ' (latest)' : '';\n lines.push(`─── Attempt #${history.length - i}${label} ───`);\n lines.push(` Date: ${attempt.completedAt ?? attempt.startedAt}`);\n lines.push(` Score: ${attempt.score}/1000 ${attempt.passed ? '✅ PASSED' : '❌ FAILED'}`);\n lines.push(` Correct: ${attempt.correctAnswers}/${attempt.totalQuestions} (${Math.round((attempt.correctAnswers / attempt.totalQuestions) * 100)}%)`);\n lines.push('');\n lines.push(' Domain Scores:');\n\n const scores = attempt.domainScores;\n for (const key of Object.keys(scores).sort()) {\n const ds = scores[key];\n lines.push(` D${ds.domainId}: ${ds.domainTitle} — ${ds.correctAnswers}/${ds.totalQuestions} (${ds.accuracyPercent}%)`);\n }\n\n // Show improvement from previous attempt\n if (i < history.length - 1) {\n const previous = history[i + 1];\n const diff = attempt.score - previous.score;\n const arrow = diff > 0 ? '↑' : diff < 0 ? '↓' : '→';\n lines.push('');\n lines.push(` Change from previous: ${arrow} ${diff > 0 ? '+' : ''}${diff} points`);\n }\n\n lines.push('');\n }\n\n // Trend summary\n if (history.length >= 2) {\n const latest = history[0].score;\n const first = history[history.length - 1].score;\n const totalImprovement = latest - first;\n lines.push('─── Overall Trend ───');\n lines.push(` First attempt: ${first}/1000`);\n lines.push(` Latest attempt: ${latest}/1000`);\n lines.push(` Total improvement: ${totalImprovement > 0 ? '+' : ''}${totalImprovement} points`);\n }\n\n return { content: [{ type: 'text' as const, text: lines.join('\\n') }] };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions, loadHandout, loadCurriculum } from '../data/loader.js';\n\nconst FOLLOW_UP_ACTIONS = ['next', 'code_example', 'concept', 'handout', 'project', 'why_wrong'] as const;\n\nconst DOMAIN_PROJECT_MAP: Readonly<Record<number, string>> = {\n 1: 'd1-agentic',\n 2: 'd2-tools',\n 3: 'd3-config',\n 4: 'd4-prompts',\n 5: 'd5-context',\n} as const;\n\nfunction extractSection(markdown: string, sectionName: string): string | null {\n const pattern = new RegExp(`^## ${sectionName}\\\\b`, 'm');\n const match = pattern.exec(markdown);\n if (!match) return null;\n\n const startIndex = match.index + match[0].length;\n const nextSectionMatch = /^## /m.exec(markdown.slice(startIndex));\n const endIndex = nextSectionMatch ? startIndex + nextSectionMatch.index : markdown.length;\n\n return markdown.slice(startIndex, endIndex).trim();\n}\n\nfunction findQuestion(questionId: string) {\n const allQuestions = loadQuestions();\n return allQuestions.find((q) => q.id === questionId) ?? null;\n}\n\nexport function registerFollowUp(server: McpServer, _db: Database.Database, _userConfig: UserConfig): void {\n server.tool(\n 'follow_up',\n 'Handle post-answer follow-up actions. Use after submit_answer to explore concepts, code examples, handouts, or reference projects.',\n {\n questionId: z.string().describe('The question ID from the previous answer'),\n action: z.enum(FOLLOW_UP_ACTIONS).describe('The follow-up action to take'),\n },\n async ({ questionId, action }) => {\n const question = findQuestion(questionId);\n\n if (!question) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Question not found', questionId }) }],\n isError: true,\n };\n }\n\n switch (action) {\n case 'next': {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n instruction: 'Call get_practice_question to get the next question.',\n taskStatement: question.taskStatement,\n domainId: question.domainId,\n }, null, 2),\n }],\n };\n }\n\n case 'code_example': {\n const handout = loadHandout(question.taskStatement);\n if (!handout) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n const codeExample = extractSection(handout, 'Code Example');\n if (!codeExample) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No Code Example section found in handout', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n taskStatement: question.taskStatement,\n codeExample,\n }, null, 2),\n }],\n };\n }\n\n case 'concept': {\n const handout = loadHandout(question.taskStatement);\n if (!handout) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n const concept = extractSection(handout, 'Concept');\n if (!concept) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No Concept section found in handout', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n taskStatement: question.taskStatement,\n concept,\n }, null, 2),\n }],\n };\n }\n\n case 'handout': {\n const handout = loadHandout(question.taskStatement);\n if (!handout) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n taskStatement: question.taskStatement,\n handout,\n }, null, 2),\n }],\n };\n }\n\n case 'project': {\n const projectId = DOMAIN_PROJECT_MAP[question.domainId] ?? null;\n if (!projectId) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No reference project mapped for this domain', domainId: question.domainId }) }],\n isError: true,\n };\n }\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n instruction: 'Call scaffold_project to explore the reference project for this domain.',\n projectId,\n domainId: question.domainId,\n }, null, 2),\n }],\n };\n }\n\n case 'why_wrong': {\n const incorrectOptions = Object.entries(question.whyWrongMap)\n .filter(([key]) => key !== question.correctAnswer)\n .reduce<Record<string, string>>((acc, [key, value]) => {\n if (value) {\n return { ...acc, [key]: value };\n }\n return acc;\n }, {});\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n questionId: question.id,\n correctAnswer: question.correctAnswer,\n explanation: question.explanation,\n whyOthersAreWrong: incorrectOptions,\n }, null, 2),\n }],\n };\n }\n }\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { CRITERIA } from '../data/criteria.js';\nimport { getActiveBuild, createBuild, updateBuildTheme } from '../db/capstone.js';\nimport { ensureUser } from '../db/users.js';\n\nfunction formatCriteria(): string {\n const lines: string[] = [];\n let currentDomain = 0;\n\n for (const criterion of CRITERIA) {\n if (criterion.domain !== currentDomain) {\n currentDomain = criterion.domain;\n if (lines.length > 0) lines.push('');\n lines.push(`Domain ${criterion.domain}: ${criterion.domainName}`);\n }\n lines.push(` ${criterion.id} — ${criterion.title}: ${criterion.description}`);\n }\n\n return lines.join('\\n');\n}\n\nfunction buildResponse(theme: string | null): string {\n const sections: string[] = [\n '=== GUIDED CAPSTONE BUILD ===',\n '',\n '--- 30 Architectural Criteria ---',\n '',\n formatCriteria(),\n ];\n\n if (theme) {\n sections.push(\n '',\n '--- Your Project Theme ---',\n theme,\n '',\n '--- Instructions ---',\n \"Review the criteria above against your project idea. Claude will analyze\",\n \"which criteria are naturally covered and suggest modifications for any gaps.\",\n \"When you're satisfied with coverage, use capstone_build_step with action\",\n \"'confirm' to begin building.\",\n );\n } else {\n sections.push(\n '',\n '--- Instructions ---',\n 'Choose a project theme that excites you. The best capstone projects are ones',\n 'you actually want to build. Provide your theme using start_capstone_build',\n \"with a 'theme' parameter, and Claude will analyze how well it covers the\",\n '30 criteria above.',\n );\n }\n\n return sections.join('\\n');\n}\n\nexport function registerStartCapstoneBuild(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'start_capstone_build',\n 'Start or refine a guided capstone build. Build your own project while learning all 30 certification task statements hands-on.',\n {\n theme: z.string().optional().describe(\"Your project idea or theme. Omit to see the 30 criteria first.\"),\n },\n async ({ theme }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n // Case 1: No theme — return criteria with instructions\n if (!theme) {\n return {\n content: [{ type: 'text' as const, text: buildResponse(null) }],\n };\n }\n\n const activeBuild = getActiveBuild(db, userId);\n\n // Case 4: Active build in 'building' status — error\n if (activeBuild && activeBuild.status === 'building') {\n return {\n content: [{\n type: 'text' as const,\n text: \"You have an active build in progress. Use capstone_build_step with action 'abandon' to start over.\",\n }],\n isError: true,\n };\n }\n\n // Case 3: Active build in 'shaping' status — update theme\n if (activeBuild && activeBuild.status === 'shaping') {\n updateBuildTheme(db, activeBuild.id, theme);\n return {\n content: [{ type: 'text' as const, text: buildResponse(theme) }],\n };\n }\n\n // Case 2: No active build — create new build\n createBuild(db, userId, theme);\n return {\n content: [{ type: 'text' as const, text: buildResponse(theme) }],\n };\n }\n );\n}\n","export interface Criterion {\n readonly id: string;\n readonly title: string;\n readonly domain: number;\n readonly domainName: string;\n readonly description: string;\n}\n\nconst DOMAIN_NAMES: Readonly<Record<number, string>> = {\n 1: 'Agentic Architecture & Orchestration',\n 2: 'Tool Design & MCP Integration',\n 3: 'Claude Code Configuration & Workflows',\n 4: 'Prompt Engineering & Structured Output',\n 5: 'Context Management & Reliability',\n} as const;\n\nexport const CRITERIA: readonly Criterion[] = [\n // Domain 1: Agentic Architecture & Orchestration\n {\n id: '1.1',\n title: 'Design and implement agentic loops for autonomous task execution',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Understanding the agentic loop lifecycle: sending requests, inspecting stop_reason, executing tools, and returning results.',\n },\n {\n id: '1.2',\n title: 'Orchestrate multi-agent systems with coordinator-subagent patterns',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Hub-and-spoke architecture, isolated context, task decomposition, and result aggregation.',\n },\n {\n id: '1.3',\n title: 'Configure subagent invocation, context passing, and spawning',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Task tool, allowedTools, explicit context passing, parallel subagent execution.',\n },\n {\n id: '1.4',\n title: 'Implement multi-step workflows with enforcement and handoff patterns',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Programmatic enforcement vs prompt-based guidance, structured handoff protocols.',\n },\n {\n id: '1.5',\n title: 'Apply Agent SDK hooks for tool call interception and data normalization',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'PostToolUse hooks, tool call interception, deterministic vs probabilistic compliance.',\n },\n {\n id: '1.6',\n title: 'Design task decomposition strategies for complex workflows',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Prompt chaining vs dynamic decomposition, per-file analysis vs cross-file integration.',\n },\n {\n id: '1.7',\n title: 'Manage session state, resumption, and forking',\n domain: 1,\n domainName: DOMAIN_NAMES[1],\n description:\n 'Named sessions, fork_session, structured summaries vs stale context.',\n },\n\n // Domain 2: Tool Design & MCP Integration\n {\n id: '2.1',\n title: 'Design effective tool interfaces with clear descriptions and boundaries',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Tool descriptions as selection mechanism, disambiguation, splitting vs consolidating.',\n },\n {\n id: '2.2',\n title: 'Implement structured error responses for MCP tools',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'isError flag, error categories, retryable vs non-retryable, structured metadata.',\n },\n {\n id: '2.3',\n title: 'Distribute tools appropriately across agents and configure tool choice',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Scoped tool access, tool_choice options, forced selection patterns.',\n },\n {\n id: '2.4',\n title: 'Integrate MCP servers into Claude Code and agent workflows',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Project vs user scope, .mcp.json, environment variable expansion, MCP resources.',\n },\n {\n id: '2.5',\n title: 'Select and apply built-in tools effectively',\n domain: 2,\n domainName: DOMAIN_NAMES[2],\n description:\n 'Grep vs Glob vs Read/Write/Edit, incremental codebase understanding.',\n },\n\n // Domain 3: Claude Code Configuration & Workflows\n {\n id: '3.1',\n title: 'Configure CLAUDE.md files with appropriate hierarchy and scoping',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'User-level, project-level, directory-level, @import syntax, .claude/rules/.',\n },\n {\n id: '3.2',\n title: 'Create and configure custom slash commands and skills',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'Project vs user scope, context: fork, allowed-tools, argument-hint frontmatter.',\n },\n {\n id: '3.3',\n title: 'Apply path-specific rules for conditional convention loading',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'YAML frontmatter paths, glob patterns, conditional activation.',\n },\n {\n id: '3.4',\n title: 'Determine when to use plan mode vs direct execution',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'Complexity assessment, architectural decisions, Explore subagent.',\n },\n {\n id: '3.5',\n title: 'Apply iterative refinement techniques for progressive improvement',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n 'Input/output examples, test-driven iteration, interview pattern.',\n },\n {\n id: '3.6',\n title: 'Integrate Claude Code into CI/CD pipelines',\n domain: 3,\n domainName: DOMAIN_NAMES[3],\n description:\n '-p flag, --output-format json, --json-schema, session context isolation.',\n },\n\n // Domain 4: Prompt Engineering & Structured Output\n {\n id: '4.1',\n title: 'Design prompts with explicit criteria to improve precision',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Explicit criteria vs vague instructions, false positive management.',\n },\n {\n id: '4.2',\n title: 'Apply few-shot prompting to improve output consistency',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Targeted examples, ambiguous case handling, format demonstration.',\n },\n {\n id: '4.3',\n title: 'Enforce structured output using tool use and JSON schemas',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'tool_use with schemas, tool_choice options, nullable fields, enum patterns.',\n },\n {\n id: '4.4',\n title: 'Implement validation, retry, and feedback loops',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Retry-with-error-feedback, limits of retry, detected_pattern tracking.',\n },\n {\n id: '4.5',\n title: 'Design efficient batch processing strategies',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Message Batches API, latency tolerance, custom_id, failure handling.',\n },\n {\n id: '4.6',\n title: 'Design multi-instance and multi-pass review architectures',\n domain: 4,\n domainName: DOMAIN_NAMES[4],\n description:\n 'Self-review limitations, independent review instances, per-file + cross-file passes.',\n },\n\n // Domain 5: Context Management & Reliability\n {\n id: '5.1',\n title: 'Manage conversation context to preserve critical information',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Progressive summarization risks, lost-in-the-middle, tool output trimming.',\n },\n {\n id: '5.2',\n title: 'Design effective escalation and ambiguity resolution patterns',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Escalation triggers, customer preferences, sentiment unreliability.',\n },\n {\n id: '5.3',\n title: 'Implement error propagation strategies across multi-agent systems',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Structured error context, access failures vs empty results, partial results.',\n },\n {\n id: '5.4',\n title: 'Manage context effectively in large codebase exploration',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Context degradation, scratchpad files, subagent delegation, /compact.',\n },\n {\n id: '5.5',\n title: 'Design human review workflows and confidence calibration',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Stratified sampling, field-level confidence, accuracy by document type.',\n },\n {\n id: '5.6',\n title: 'Preserve information provenance and handle uncertainty in synthesis',\n domain: 5,\n domainName: DOMAIN_NAMES[5],\n description:\n 'Claim-source mappings, conflict annotation, temporal data handling.',\n },\n] as const;\n","import crypto from 'node:crypto';\nimport type Database from 'better-sqlite3';\nimport type { CapstoneBuild, CapstoneBuildStep, BuildStepTemplate, BuildStepUpdates } from '../types.js';\n\nexport function getActiveBuild(db: Database.Database, userId: string): CapstoneBuild | null {\n const row = db.prepare(\n `SELECT * FROM capstone_builds WHERE userId = ? AND status IN ('shaping', 'building') ORDER BY createdAt DESC LIMIT 1`\n ).get(userId) as CapstoneBuild | undefined;\n return row ?? null;\n}\n\nexport function createBuild(db: Database.Database, userId: string, theme: string): CapstoneBuild {\n const id = crypto.randomUUID();\n const now = new Date().toISOString();\n db.prepare(\n `INSERT INTO capstone_builds (id, userId, theme, currentStep, status, themeValidated, createdAt, updatedAt)\n VALUES (?, ?, ?, 0, 'shaping', 0, ?, ?)`\n ).run(id, userId, theme, now, now);\n return db.prepare('SELECT * FROM capstone_builds WHERE id = ?').get(id) as CapstoneBuild;\n}\n\nexport function updateBuildTheme(db: Database.Database, buildId: string, theme: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET theme = ?, updatedAt = ? WHERE id = ?`\n ).run(theme, now, buildId);\n}\n\nexport function confirmBuild(db: Database.Database, buildId: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET status = 'building', themeValidated = 1, currentStep = 1, updatedAt = ? WHERE id = ?`\n ).run(now, buildId);\n}\n\nexport function abandonBuild(db: Database.Database, buildId: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET status = 'abandoned', updatedAt = ? WHERE id = ?`\n ).run(now, buildId);\n}\n\nexport function completeBuild(db: Database.Database, buildId: string): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET status = 'completed', updatedAt = ? WHERE id = ?`\n ).run(now, buildId);\n}\n\nexport function getBuildStep(db: Database.Database, buildId: string, stepIndex: number): CapstoneBuildStep | null {\n const row = db.prepare(\n `SELECT * FROM capstone_build_steps WHERE buildId = ? AND stepIndex = ?`\n ).get(buildId, stepIndex) as CapstoneBuildStep | undefined;\n return row ?? null;\n}\n\nexport function createBuildSteps(db: Database.Database, buildId: string, steps: readonly BuildStepTemplate[]): void {\n const now = new Date().toISOString();\n const insert = db.prepare(\n `INSERT INTO capstone_build_steps (id, buildId, stepIndex, fileName, taskStatements, quizQuestionIds, quizCompleted, buildCompleted, walkthroughViewed, createdAt, updatedAt)\n VALUES (?, ?, ?, ?, ?, NULL, 0, 0, 0, ?, ?)`\n );\n const insertAll = db.transaction((stepsToInsert: readonly BuildStepTemplate[]) => {\n for (const step of stepsToInsert) {\n insert.run(\n crypto.randomUUID(),\n buildId,\n step.stepIndex,\n step.fileName,\n JSON.stringify(step.taskStatements),\n now,\n now\n );\n }\n });\n insertAll(steps);\n}\n\nexport function updateBuildStep(db: Database.Database, stepId: string, updates: Partial<BuildStepUpdates>): void {\n const now = new Date().toISOString();\n const setClauses: string[] = ['updatedAt = ?'];\n const params: (string | number)[] = [now];\n\n if (updates.quizCompleted !== undefined) {\n setClauses.push('quizCompleted = ?');\n params.push(updates.quizCompleted);\n }\n if (updates.buildCompleted !== undefined) {\n setClauses.push('buildCompleted = ?');\n params.push(updates.buildCompleted);\n }\n if (updates.walkthroughViewed !== undefined) {\n setClauses.push('walkthroughViewed = ?');\n params.push(updates.walkthroughViewed);\n }\n\n params.push(stepId);\n db.prepare(`UPDATE capstone_build_steps SET ${setClauses.join(', ')} WHERE id = ?`).run(...params);\n}\n\nexport function setQuizQuestionIds(db: Database.Database, stepId: string, questionIds: readonly string[]): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_build_steps SET quizQuestionIds = ?, updatedAt = ? WHERE id = ?`\n ).run(JSON.stringify(questionIds), now, stepId);\n}\n\nexport function advanceBuildStep(db: Database.Database, buildId: string, nextStep: number): void {\n const now = new Date().toISOString();\n db.prepare(\n `UPDATE capstone_builds SET currentStep = ?, updatedAt = ? WHERE id = ?`\n ).run(nextStep, now, buildId);\n}\n\nexport function getBuildSteps(db: Database.Database, buildId: string): readonly CapstoneBuildStep[] {\n return db.prepare(\n `SELECT * FROM capstone_build_steps WHERE buildId = ? ORDER BY stepIndex ASC`\n ).all(buildId) as CapstoneBuildStep[];\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, CapstoneBuild, CapstoneBuildStep } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\nimport { BUILD_STEPS } from '../data/build-steps.js';\nimport { CRITERIA } from '../data/criteria.js';\nimport { ensureUser } from '../db/users.js';\nimport {\n getActiveBuild,\n confirmBuild,\n createBuildSteps,\n getBuildStep,\n setQuizQuestionIds,\n updateBuildStep,\n advanceBuildStep,\n completeBuild,\n abandonBuild,\n getBuildSteps,\n} from '../db/capstone.js';\nimport { elicitSingleSelect } from './elicit.js';\n\nconst ACTIONS = ['confirm', 'quiz', 'build', 'next', 'status', 'abandon'] as const;\n\nconst TOTAL_STEPS = 18;\n\nfunction errorResponse(message: string) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: message }) }],\n isError: true,\n };\n}\n\nfunction textResponse(data: unknown) {\n return {\n content: [{ type: 'text' as const, text: typeof data === 'string' ? data : JSON.stringify(data, null, 2) }],\n };\n}\n\nfunction getStepTemplate(stepIndex: number) {\n return BUILD_STEPS.find((s) => s.stepIndex === stepIndex) ?? null;\n}\n\nfunction formatStepPreview(step: CapstoneBuildStep, template: ReturnType<typeof getStepTemplate>) {\n const taskIds = JSON.parse(step.taskStatements) as readonly string[];\n const criteria = taskIds\n .map((id) => CRITERIA.find((c) => c.id === id))\n .filter(Boolean);\n\n return [\n `=== Step ${step.stepIndex}/${TOTAL_STEPS}: ${step.fileName} ===`,\n '',\n `Description: ${template?.description ?? 'N/A'}`,\n '',\n '--- Task Statements ---',\n ...criteria.map((c) => ` ${c!.id}: ${c!.title}`),\n '',\n 'Next action: Call capstone_build_step with action \"quiz\" to get quiz questions for this step.',\n ].join('\\n');\n}\n\nfunction shuffleArray<T>(arr: readonly T[]): readonly T[] {\n const copy = [...arr];\n for (let i = copy.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [copy[i], copy[j]] = [copy[j], copy[i]];\n }\n return copy;\n}\n\nfunction getAnsweredQuestionIdsForBuild(db: Database.Database, userId: string, questionIds: readonly string[]): Set<string> {\n if (questionIds.length === 0) return new Set();\n const placeholders = questionIds.map(() => '?').join(', ');\n const rows = db.prepare(\n `SELECT DISTINCT questionId FROM answers WHERE userId = ? AND questionId IN (${placeholders})`\n ).all(userId, ...questionIds) as Array<{ questionId: string }>;\n return new Set(rows.map((r) => r.questionId));\n}\n\nfunction handleConfirm(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found. Use capstone_theme to start a new build.');\n }\n if (build.status !== 'shaping') {\n return errorResponse(`Build is already in \"${build.status}\" status. Only \"shaping\" builds can be confirmed.`);\n }\n\n confirmBuild(db, build.id);\n createBuildSteps(db, build.id, BUILD_STEPS);\n\n const step = getBuildStep(db, build.id, 1);\n if (!step) {\n return errorResponse('Failed to create build steps.');\n }\n\n const template = getStepTemplate(1);\n return textResponse(formatStepPreview(step, template));\n}\n\nfunction handleQuiz(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n if (build.status !== 'building') {\n return errorResponse(`Build must be in \"building\" status to get quiz questions. Current status: \"${build.status}\".`);\n }\n\n const step = getBuildStep(db, build.id, build.currentStep);\n if (!step) {\n return errorResponse(`Build step ${build.currentStep} not found.`);\n }\n\n if (step.quizCompleted === 1) {\n return errorResponse('Quiz already completed for this step. Use action \"build\" to get build instructions.');\n }\n\n const taskIds = JSON.parse(step.taskStatements) as readonly string[];\n const allQuestions = loadQuestions();\n const stepQuestions = allQuestions.filter((q) => taskIds.includes(q.taskStatement));\n\n if (stepQuestions.length === 0) {\n return errorResponse(`No questions found for task statements: ${taskIds.join(', ')}`);\n }\n\n const shuffled = shuffleArray(stepQuestions);\n const quizCount = Math.min(shuffled.length, taskIds.length >= 3 ? 3 : 2);\n const selected = shuffled.slice(0, quizCount);\n const selectedIds = selected.map((q) => q.id);\n\n setQuizQuestionIds(db, step.id, selectedIds);\n\n const formattedQuestions = selected.map((q) => ({\n questionId: q.id,\n taskStatement: q.taskStatement,\n difficulty: q.difficulty,\n scenario: q.scenario,\n text: q.text,\n options: q.options,\n }));\n\n return textResponse({\n step: step.stepIndex,\n fileName: step.fileName,\n quizQuestions: formattedQuestions,\n instruction: 'Answer each question using the submit_answer tool.',\n });\n}\n\nfunction handleBuild(db: Database.Database, userId: string, build: CapstoneBuild): ReturnType<typeof textResponse> {\n const step = getBuildStep(db, build.id, build.currentStep);\n if (!step) {\n return errorResponse(`Build step ${build.currentStep} not found.`);\n }\n\n if (step.quizQuestionIds) {\n const questionIds = JSON.parse(step.quizQuestionIds) as readonly string[];\n const answered = getAnsweredQuestionIdsForBuild(db, userId, questionIds);\n const remaining = questionIds.filter((id) => !answered.has(id));\n\n if (remaining.length > 0) {\n return errorResponse(\n `Not all quiz questions answered. Remaining question IDs: ${remaining.join(', ')}. Use submit_answer to answer them first.`\n );\n }\n\n if (step.quizCompleted !== 1) {\n updateBuildStep(db, step.id, { quizCompleted: 1 });\n }\n }\n\n updateBuildStep(db, step.id, { buildCompleted: 1 });\n\n const template = getStepTemplate(build.currentStep);\n const taskIds = JSON.parse(step.taskStatements) as readonly string[];\n const criteria = taskIds\n .map((id) => CRITERIA.find((c) => c.id === id))\n .filter(Boolean);\n\n const taskDetails = criteria.map((c) => [\n ` ${c!.id}: ${c!.title}`,\n ` ${c!.description}`,\n ` Code hints: ${template?.codeHints ?? 'N/A'}`,\n ].join('\\n')).join('\\n\\n');\n\n const output = [\n `=== Step ${build.currentStep}/${TOTAL_STEPS}: ${step.fileName} ===`,\n '',\n `Theme: ${build.theme}`,\n `Task Statements: ${taskIds.join(', ')}`,\n '',\n '--- Build Instructions ---',\n `Generate the code for ${step.fileName} themed to the user's project above.`,\n 'The code should demonstrate these certification concepts:',\n '',\n taskDetails,\n '',\n 'After generating the code, provide a walkthrough explaining each section:',\n '- What the code does',\n '- Which task statement it demonstrates',\n '- How it connects to the broader architecture',\n '',\n '--- Task Statement Details ---',\n ...criteria.map((c) => `${c!.id} — ${c!.title}: ${c!.description}`),\n ].join('\\n');\n\n return textResponse(output);\n}\n\nfunction handleNext(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n if (build.status !== 'building') {\n return errorResponse(`Build must be in \"building\" status. Current status: \"${build.status}\".`);\n }\n\n const step = getBuildStep(db, build.id, build.currentStep);\n if (!step) {\n return errorResponse(`Build step ${build.currentStep} not found.`);\n }\n if (step.buildCompleted !== 1) {\n return errorResponse('Current step build is not completed. Use action \"build\" first.');\n }\n\n if (build.currentStep >= TOTAL_STEPS) {\n completeBuild(db, build.id);\n\n const allSteps = getBuildSteps(db, build.id);\n const completedCount = allSteps.filter((s) => s.buildCompleted === 1).length;\n\n return textResponse({\n status: 'completed',\n message: 'Congratulations! You have completed all 18 capstone build steps.',\n theme: build.theme,\n stepsCompleted: completedCount,\n totalSteps: TOTAL_STEPS,\n instruction: 'Review your completed project files and ensure all certification concepts are demonstrated.',\n });\n }\n\n const nextStepIndex = build.currentStep + 1;\n advanceBuildStep(db, build.id, nextStepIndex);\n\n const nextStep = getBuildStep(db, build.id, nextStepIndex);\n if (!nextStep) {\n return errorResponse(`Next step ${nextStepIndex} not found.`);\n }\n\n const template = getStepTemplate(nextStepIndex);\n return textResponse(formatStepPreview(nextStep, template));\n}\n\nfunction handleStatus(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n\n const allSteps = getBuildSteps(db, build.id);\n const completedSteps = allSteps.filter((s) => s.buildCompleted === 1);\n const remainingSteps = allSteps.filter((s) => s.buildCompleted !== 1);\n\n const coveredTaskIds = new Set(\n completedSteps.flatMap((s) => JSON.parse(s.taskStatements) as string[])\n );\n const totalCriteria = CRITERIA.length;\n const coveredCriteria = CRITERIA.filter((c) => coveredTaskIds.has(c.id)).length;\n\n return textResponse({\n buildId: build.id,\n theme: build.theme,\n status: build.status,\n currentStep: build.currentStep,\n stepsCompleted: completedSteps.length,\n stepsRemaining: remainingSteps.length,\n totalSteps: TOTAL_STEPS,\n criteriaCoverage: `${coveredCriteria}/${totalCriteria}`,\n completedFiles: completedSteps.map((s) => s.fileName),\n remainingFiles: remainingSteps.map((s) => s.fileName),\n });\n}\n\nfunction handleAbandon(db: Database.Database, userId: string): ReturnType<typeof textResponse> {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found to abandon.');\n }\n\n abandonBuild(db, build.id);\n\n return textResponse({\n status: 'abandoned',\n message: `Build \"${build.theme}\" has been abandoned.`,\n buildId: build.id,\n });\n}\n\nfunction appendSelectedAction(\n response: ReturnType<typeof textResponse>,\n selected: string | null,\n): ReturnType<typeof textResponse> {\n if (!selected) return response;\n\n const existingText = response.content[0].text;\n return {\n ...response,\n content: [{ type: 'text' as const, text: `${existingText}\\n\\nUser selected next action: ${selected}` }],\n };\n}\n\nexport function registerCapstoneBuildStep(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'capstone_build_step',\n 'Drive your guided capstone build — quiz, build, and advance through 18 progressive steps.',\n {\n action: z.enum(ACTIONS).describe('The build action: confirm, quiz, build, next, status, or abandon'),\n },\n async ({ action }) => {\n const userId = userConfig.userId;\n ensureUser(db, userId);\n\n switch (action) {\n case 'confirm': {\n const result = handleConfirm(db, userId);\n if ('isError' in result) return result;\n const selected = await elicitSingleSelect(\n server,\n 'Build confirmed! What would you like to do next?',\n 'nextAction',\n [{ value: 'quiz', title: 'Start the first quiz' }],\n );\n return appendSelectedAction(result, selected);\n }\n\n case 'quiz':\n return handleQuiz(db, userId);\n\n case 'build': {\n const build = getActiveBuild(db, userId);\n if (!build) {\n return errorResponse('No active build found.');\n }\n if (build.status !== 'building') {\n return errorResponse(`Build must be in \"building\" status. Current status: \"${build.status}\".`);\n }\n const result = handleBuild(db, userId, build);\n if ('isError' in result) return result;\n const selected = await elicitSingleSelect(\n server,\n 'Build instructions generated. What would you like to do next?',\n 'nextAction',\n [\n { value: 'next', title: 'Advance to the next step' },\n { value: 'status', title: 'Check build progress' },\n ],\n );\n return appendSelectedAction(result, selected);\n }\n\n case 'next': {\n const result = handleNext(db, userId);\n if ('isError' in result) return result;\n const selected = await elicitSingleSelect(\n server,\n 'Step advanced. What would you like to do next?',\n 'nextAction',\n [\n { value: 'quiz', title: 'Start this step\\'s quiz' },\n { value: 'status', title: 'Check build progress' },\n ],\n );\n return appendSelectedAction(result, selected);\n }\n\n case 'status':\n return handleStatus(db, userId);\n\n case 'abandon':\n return handleAbandon(db, userId);\n }\n }\n );\n}\n","export interface BuildStep {\n readonly stepIndex: number;\n readonly fileName: string;\n readonly taskStatements: readonly string[];\n readonly description: string;\n readonly codeHints: string;\n}\n\nexport const BUILD_STEPS: readonly BuildStep[] = [\n {\n stepIndex: 1,\n fileName: 'CLAUDE.md, .claude/',\n taskStatements: ['3.1', '3.2', '3.3'],\n description: 'Project config and rules',\n codeHints:\n 'Generate a CLAUDE.md with hierarchical instructions, @import references, and .claude/rules/ with path-scoped YAML frontmatter. Include a custom slash command definition.',\n },\n {\n stepIndex: 2,\n fileName: 'package.json, tsconfig.json',\n taskStatements: ['3.4'],\n description: 'Project setup and CI hooks',\n codeHints:\n 'Set up TypeScript project configuration with strict compiler options, lint/test scripts suitable for plan-mode assessment, and pre-commit hooks.',\n },\n {\n stepIndex: 3,\n fileName: 'src/server.ts',\n taskStatements: ['2.1', '2.2'],\n description: 'MCP server with tool registration',\n codeHints:\n 'Create an MCP server entry point that registers tools with clear descriptions and boundaries, and returns structured error responses with isError flags.',\n },\n {\n stepIndex: 4,\n fileName: 'src/tools/',\n taskStatements: ['2.1', '2.3', '2.5'],\n description: 'Tool definitions and scoping',\n codeHints:\n 'Define tool modules with scoped access per agent, tool_choice configuration, and demonstrate effective use of built-in tools like Grep, Glob, and Read.',\n },\n {\n stepIndex: 5,\n fileName: 'src/error-handling.ts',\n taskStatements: ['2.2'],\n description: 'Error boundaries and recovery',\n codeHints:\n 'Implement error boundary utilities that categorize errors as retryable vs non-retryable, attach structured metadata, and format MCP-compliant error responses.',\n },\n {\n stepIndex: 6,\n fileName: 'src/coordinator.ts',\n taskStatements: ['1.1', '1.2', '1.6'],\n description: 'Main agentic loop',\n codeHints:\n 'Build a coordinator that runs the agentic loop (send request, inspect stop_reason, execute tools, return results) with hub-and-spoke orchestration and task decomposition.',\n },\n {\n stepIndex: 7,\n fileName: 'src/subagents/',\n taskStatements: ['1.3', '1.4'],\n description: 'Subagent definitions and routing',\n codeHints:\n 'Define subagent configurations with allowedTools, explicit context passing, and structured handoff protocols for multi-step workflow enforcement.',\n },\n {\n stepIndex: 8,\n fileName: 'src/hooks.ts',\n taskStatements: ['1.5'],\n description: 'Pre/post tool-use hooks',\n codeHints:\n 'Implement PostToolUse hooks that intercept tool calls for data normalization, demonstrating deterministic compliance checks vs probabilistic validation.',\n },\n {\n stepIndex: 9,\n fileName: 'src/workflow.ts',\n taskStatements: ['1.4', '1.6'],\n description: 'Multi-step workflows',\n codeHints:\n 'Create workflow orchestration with programmatic enforcement gates, prompt chaining stages, and per-file analysis that feeds into cross-file integration.',\n },\n {\n stepIndex: 10,\n fileName: 'src/session.ts',\n taskStatements: ['1.7'],\n description: 'Session and state management',\n codeHints:\n 'Implement session lifecycle with named sessions, fork_session for parallel exploration, and structured summaries to avoid stale context on resumption.',\n },\n {\n stepIndex: 11,\n fileName: 'src/prompts/system.ts',\n taskStatements: ['4.1', '4.2'],\n description: 'System prompts with few-shot',\n codeHints:\n 'Design system prompts with explicit criteria for precision, and embed few-shot examples that handle ambiguous cases and demonstrate expected output format.',\n },\n {\n stepIndex: 12,\n fileName: 'src/prompts/extraction.ts',\n taskStatements: ['4.3', '4.4'],\n description: 'Structured output and validation',\n codeHints:\n 'Enforce structured output via tool_use with JSON schemas and enum patterns, plus retry-with-error-feedback loops that track detected_pattern for progressive improvement.',\n },\n {\n stepIndex: 13,\n fileName: 'src/prompts/batch.ts',\n taskStatements: ['4.5', '4.6'],\n description: 'Batch processing and multi-pass',\n codeHints:\n 'Implement batch processing using the Message Batches API with custom_id tracking and failure handling, plus multi-pass review with independent instances.',\n },\n {\n stepIndex: 14,\n fileName: 'src/context/preservation.ts',\n taskStatements: ['5.1'],\n description: 'Context preservation strategies',\n codeHints:\n 'Implement context preservation that mitigates progressive summarization risks and lost-in-the-middle effects, with tool output trimming to retain critical information.',\n },\n {\n stepIndex: 15,\n fileName: 'src/context/triggers.ts',\n taskStatements: ['5.2'],\n description: 'Context refresh triggers',\n codeHints:\n 'Define escalation triggers and ambiguity resolution patterns that detect when context needs refreshing, using customer preference signals rather than unreliable sentiment.',\n },\n {\n stepIndex: 16,\n fileName: 'src/context/propagation.ts',\n taskStatements: ['5.3'],\n description: 'Cross-agent context propagation',\n codeHints:\n 'Implement structured error context propagation across agents, distinguishing access failures from empty results and handling partial result aggregation.',\n },\n {\n stepIndex: 17,\n fileName: 'src/context/scratchpad.ts',\n taskStatements: ['5.4'],\n description: 'Scratchpad and subagent delegation',\n codeHints:\n 'Build scratchpad file management for large codebase exploration, with subagent delegation to prevent context degradation and /compact integration.',\n },\n {\n stepIndex: 18,\n fileName: 'src/context/confidence.ts',\n taskStatements: ['5.5', '5.6'],\n description: 'Confidence calibration and synthesis',\n codeHints:\n 'Implement field-level confidence scoring with stratified sampling for human review, plus claim-source mappings with conflict annotation for provenance tracking.',\n },\n] as const;\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig, CapstoneBuildStep } from '../types.js';\nimport { getActiveBuild, getBuildSteps } from '../db/capstone.js';\nimport { BUILD_STEPS } from '../data/build-steps.js';\nimport { CRITERIA } from '../data/criteria.js';\n\ninterface QuizStats {\n readonly domainId: number;\n readonly total: number;\n readonly correct: number;\n}\n\nfunction collectQuizQuestionIds(steps: readonly CapstoneBuildStep[]): readonly string[] {\n return steps.flatMap(step => {\n if (!step.quizQuestionIds) return [];\n const parsed = JSON.parse(step.quizQuestionIds) as readonly string[];\n return [...parsed];\n });\n}\n\nfunction getQuizPerformance(db: Database.Database, userId: string, questionIds: readonly string[]): readonly QuizStats[] {\n if (questionIds.length === 0) return [];\n\n const placeholders = questionIds.map(() => '?').join(', ');\n const rows = db.prepare(\n `SELECT domainId, COUNT(*) as total, SUM(CASE WHEN isCorrect THEN 1 ELSE 0 END) as correct\n FROM answers\n WHERE userId = ? AND questionId IN (${placeholders})\n GROUP BY domainId\n ORDER BY domainId ASC`\n ).all(userId, ...questionIds) as Array<{ domainId: number; total: number; correct: number }>;\n\n return rows.map(r => ({\n domainId: r.domainId,\n total: r.total,\n correct: r.correct ?? 0,\n }));\n}\n\nfunction countCoveredCriteria(completedSteps: readonly CapstoneBuildStep[]): number {\n const coveredIds = new Set<string>();\n for (const step of completedSteps) {\n if (!step.buildCompleted) continue;\n const taskStatements = JSON.parse(step.taskStatements) as readonly string[];\n for (const ts of taskStatements) {\n coveredIds.add(ts);\n }\n }\n return coveredIds.size;\n}\n\nfunction formatBuildingStatus(\n theme: string,\n currentStep: number,\n steps: readonly CapstoneBuildStep[],\n quizPerformance: readonly QuizStats[],\n): string {\n const totalSteps = BUILD_STEPS.length;\n const totalCriteria = CRITERIA.length;\n const coveredCriteria = countCoveredCriteria(steps);\n const remainingCriteria = totalCriteria - coveredCriteria;\n\n const stepLines = BUILD_STEPS.map(template => {\n const dbStep = steps.find(s => s.stepIndex === template.stepIndex);\n const isCompleted = dbStep?.buildCompleted === 1;\n const isCurrent = template.stepIndex === currentStep;\n const marker = isCompleted ? '[x]' : '[ ]';\n const suffix = isCurrent && !isCompleted ? ' \\u2190 current' : '';\n const criteria = template.taskStatements.join(', ');\n return ` ${marker} Step ${template.stepIndex}: ${template.fileName} (${criteria})${suffix}`;\n });\n\n const quizLines = quizPerformance.length > 0\n ? quizPerformance.map(q => {\n const pct = q.total > 0 ? Math.round((q.correct / q.total) * 100) : 0;\n return ` Domain ${q.domainId}: ${q.correct}/${q.total} correct (${pct}%)`;\n })\n : [' No quiz answers yet.'];\n\n const sections = [\n '=== CAPSTONE BUILD PROGRESS ===',\n '',\n `Theme: ${theme}`,\n 'Status: Building',\n `Current Step: ${currentStep}/${totalSteps}`,\n '',\n '--- Completed Steps ---',\n ...stepLines,\n '',\n '--- Criteria Coverage ---',\n ` Covered: ${coveredCriteria}/${totalCriteria} task statements`,\n ` Remaining: ${remainingCriteria} task statements`,\n '',\n '--- Quiz Performance ---',\n ...quizLines,\n ];\n\n return sections.join('\\n');\n}\n\nexport function registerCapstoneBuildStatus(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.tool(\n 'capstone_build_status',\n 'Check your guided capstone build progress \\u2014 current step, criteria coverage, and quiz performance.',\n {},\n async () => {\n const userId = userConfig.userId;\n const build = getActiveBuild(db, userId);\n\n if (!build) {\n return {\n content: [{\n type: 'text' as const,\n text: 'No active capstone build found. Use start_capstone_build to begin a guided build.',\n }],\n };\n }\n\n if (build.status === 'shaping') {\n const lines = [\n '=== CAPSTONE BUILD STATUS ===',\n '',\n `Theme: ${build.theme}`,\n 'Status: Shaping',\n '',\n 'Your theme is being shaped. You can:',\n ' - Confirm it to start building',\n ' - Refine it with a new description',\n ];\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n };\n }\n\n // Status is 'building'\n const steps = getBuildSteps(db, build.id);\n const quizQuestionIds = collectQuizQuestionIds(steps);\n const quizPerformance = getQuizPerformance(db, userId, quizQuestionIds);\n\n const text = formatBuildingStatus(build.theme, build.currentStep, steps, quizPerformance);\n\n return {\n content: [{ type: 'text' as const, text }],\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { registerSubmitAnswer } from './submit-answer.js';\nimport { registerGetProgress } from './get-progress.js';\nimport { registerGetCurriculum } from './get-curriculum.js';\nimport { registerGetSectionDetails } from './get-section-details.js';\nimport { registerGetPracticeQuestion } from './get-practice-question.js';\nimport { registerStartAssessment } from './start-assessment.js';\nimport { registerGetWeakAreas } from './get-weak-areas.js';\nimport { registerGetStudyPlan } from './get-study-plan.js';\nimport { registerScaffoldProject } from './scaffold-project.js';\nimport { registerResetProgress } from './reset-progress.js';\nimport { registerStartPracticeExam } from './start-practice-exam.js';\nimport { registerSubmitExamAnswer } from './submit-exam-answer.js';\nimport { registerGetExamHistory } from './get-exam-history.js';\nimport { registerFollowUp } from './follow-up.js';\nimport { registerStartCapstoneBuild } from './start-capstone-build.js';\nimport { registerCapstoneBuildStep } from './capstone-build-step.js';\nimport { registerCapstoneBuildStatus } from './capstone-build-status.js';\n\nexport function registerTools(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n registerSubmitAnswer(server, db, userConfig);\n registerGetProgress(server, db, userConfig);\n registerGetCurriculum(server, db, userConfig);\n registerGetSectionDetails(server, db, userConfig);\n registerGetPracticeQuestion(server, db, userConfig);\n registerStartAssessment(server, db, userConfig);\n registerGetWeakAreas(server, db, userConfig);\n registerGetStudyPlan(server, db, userConfig);\n registerScaffoldProject(server, db, userConfig);\n registerResetProgress(server, db, userConfig);\n registerStartPracticeExam(server, db, userConfig);\n registerSubmitExamAnswer(server, db, userConfig);\n registerGetExamHistory(server, db, userConfig);\n registerFollowUp(server, db, userConfig);\n registerStartCapstoneBuild(server, db, userConfig);\n registerCapstoneBuildStep(server, db, userConfig);\n registerCapstoneBuildStatus(server, db, userConfig);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadQuestions } from '../data/loader.js';\n\nexport function registerPrompts(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n server.prompt(\n 'quiz_question',\n 'Present a certification exam question with clickable A/B/C/D options',\n { questionId: z.string().describe('Question ID to present') },\n async ({ questionId }) => {\n const questions = loadQuestions();\n const question = questions.find(q => q.id === questionId);\n if (!question) {\n return { messages: [{ role: 'user' as const, content: { type: 'text' as const, text: 'Question not found.' } }] };\n }\n return {\n messages: [{\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: `**${question.scenario}**\\n\\n${question.text}\\n\\n A) ${question.options.A}\\n B) ${question.options.B}\\n C) ${question.options.C}\\n D) ${question.options.D}\\n\\nSelect your answer (A/B/C/D):`,\n },\n }],\n };\n }\n );\n\n server.prompt(\n 'choose_mode',\n 'Select a study mode for the current session',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: 'How would you like to study?\\n\\n1. **Guided Capstone** — Work through the reference project touching all domains\\n2. **Dynamic Exercises** — Targeted questions based on your weak areas\\n3. **Quick Quiz** — Rapid-fire questions across all domains\\n4. **Review Weak Areas** — Focus on topics you\\'ve struggled with\\n\\nChoose a mode (1-4):',\n },\n }],\n })\n );\n\n server.prompt(\n 'assessment_question',\n 'Present an assessment question with A/B/C/D options',\n { questionId: z.string().describe('Assessment question ID'), questionNumber: z.string().describe('Current question number (1-15)') },\n async ({ questionId, questionNumber }) => {\n const question = loadQuestions().find(q => q.id === questionId);\n if (!question) return { messages: [{ role: 'user' as const, content: { type: 'text' as const, text: 'Question not found.' } }] };\n return {\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: `**Assessment Question ${questionNumber}/15**\\n\\n${question.scenario}\\n\\n${question.text}\\n\\n A) ${question.options.A}\\n B) ${question.options.B}\\n C) ${question.options.C}\\n D) ${question.options.D}\\n\\nSelect your answer:` },\n }],\n };\n }\n );\n\n server.prompt(\n 'choose_domain',\n 'Select which domain to study',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: 'Which domain would you like to study?\\n\\n1. **Agentic Architecture & Orchestration** (27%)\\n2. **Tool Design & MCP Integration** (18%)\\n3. **Claude Code Configuration & Workflows** (20%)\\n4. **Prompt Engineering & Structured Output** (20%)\\n5. **Context Management & Reliability** (15%)\\n\\nChoose a domain (1-5):' },\n }],\n })\n );\n\n server.prompt(\n 'choose_difficulty',\n 'Select question difficulty level',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: 'Choose your difficulty level:\\n\\n1. **Easy** — Concept recall and basic understanding\\n2. **Medium** — Applied scenarios requiring analysis\\n3. **Hard** — Complex multi-step reasoning\\n\\nSelect difficulty (1-3):' },\n }],\n })\n );\n\n server.prompt(\n 'post_answer_options',\n 'Present options after answering a question',\n { wasCorrect: z.string().describe('Whether the previous answer was correct') },\n async ({ wasCorrect }) => {\n const options = wasCorrect === 'true'\n ? '1. **Next Question** — Continue with the next question\\n2. **Explain Further** — Show a deeper explanation with code example\\n3. **View Handout** — Read the concept lesson for this topic\\n4. **Change Topic** — Switch to a different domain'\n : '1. **Next Question** — Continue with the next question\\n2. **Explain Why I Was Wrong** — Show a detailed explanation with code example\\n3. **View Concept Lesson** — Review the concept before continuing\\n4. **Try Similar Question** — Get another question on this same topic';\n return {\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: `What would you like to do next?\\n\\n${options}\\n\\nChoose an option (1-4):` },\n }],\n };\n }\n );\n\n server.prompt(\n 'skip_options',\n 'Present options to skip or customize the current content',\n {},\n async () => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: 'This topic has a concept lesson before the questions.\\n\\n1. **Read Lesson** — Learn the concept first (recommended for new topics)\\n2. **Skip to Questions** — Go straight to practice questions\\n3. **Quick Summary** — Get a 3-line summary then start questions\\n\\nChoose an option (1-3):' },\n }],\n })\n );\n\n server.prompt(\n 'confirm_action',\n 'Confirm a destructive action like resetting progress',\n { action: z.string().describe('The action to confirm') },\n async ({ action }) => ({\n messages: [{\n role: 'user' as const,\n content: { type: 'text' as const, text: `Are you sure?\\n\\nThis will ${action}. This action cannot be undone.\\n\\n1. **Yes, proceed** — Confirm the action\\n2. **No, cancel** — Go back\\n\\nChoose (1-2):` },\n }],\n })\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type Database from 'better-sqlite3';\nimport type { UserConfig } from '../types.js';\nimport { loadCurriculum, loadHandout } from '../data/loader.js';\nimport { recordHandoutView } from '../db/handout-views.js';\nimport { getQuizWidgetHtml } from '../ui/loader.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport function registerResources(server: McpServer, db: Database.Database, userConfig: UserConfig): void {\n // 1. Handouts as dynamic resource\n server.resource(\n 'handout',\n new ResourceTemplate('handout://{taskStatement}', {\n list: async () => {\n const curriculum = loadCurriculum();\n const resources = curriculum.domains.flatMap(d =>\n d.taskStatements.map(ts => ({\n uri: `handout://${ts.id}`,\n name: `${ts.id} — ${ts.title}`,\n mimeType: 'text/markdown' as const,\n }))\n );\n return { resources };\n },\n }),\n { mimeType: 'text/markdown' },\n async (uri, { taskStatement }) => {\n const ts = taskStatement as string;\n const content = loadHandout(ts);\n recordHandoutView(db, userConfig.userId, ts);\n return {\n contents: [{\n uri: uri.href,\n text: content ?? `Handout for ${ts} is not yet available.`,\n mimeType: 'text/markdown',\n }],\n };\n }\n );\n\n // 2. Reference projects as dynamic resource\n server.resource(\n 'reference-project',\n new ResourceTemplate('reference-project://{projectId}', {\n list: async () => ({\n resources: [\n { uri: 'reference-project://capstone', name: 'Capstone — Multi-Agent Research System', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d1-agentic', name: 'D1 Mini — Agentic Loop', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d2-tools', name: 'D2 Mini — Tool Design', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d3-config', name: 'D3 Mini — Claude Code Config', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d4-prompts', name: 'D4 Mini — Prompt Engineering', mimeType: 'text/markdown' as const },\n { uri: 'reference-project://d5-context', name: 'D5 Mini — Context Management', mimeType: 'text/markdown' as const },\n ],\n }),\n }),\n { mimeType: 'text/markdown' },\n async (uri, { projectId }) => {\n const id = projectId as string;\n const projectPath = path.join(__dirname, '..', '..', 'projects', id, 'README.md');\n const content = fs.existsSync(projectPath)\n ? fs.readFileSync(projectPath, 'utf-8')\n : `Reference project \"${id}\" is not yet available. It will be added in the content creation phase.`;\n return {\n contents: [{ uri: uri.href, text: content, mimeType: 'text/markdown' }],\n };\n }\n );\n\n // 3. Quiz widget UI resource (MCP App)\n server.resource(\n 'quiz-widget',\n 'ui://connectry-architect/quiz',\n { mimeType: 'text/html;profile=mcp-app' },\n async (uri) => ({\n contents: [{\n uri: uri.href,\n mimeType: 'text/html;profile=mcp-app',\n text: getQuizWidgetHtml(),\n }],\n }),\n );\n\n // 4. Exam info as static resource\n server.resource(\n 'exam-info',\n 'exam-info://overview',\n { mimeType: 'text/markdown' },\n async (uri) => ({\n contents: [{\n uri: uri.href,\n text: EXAM_INFO_MARKDOWN,\n mimeType: 'text/markdown',\n }],\n })\n );\n}\n\nconst EXAM_INFO_MARKDOWN = `# Claude Certified Architect — Foundations\n\n## Exam Format\n- Multiple choice (1 correct, 3 distractors)\n- Scenario-based questions (4 of 6 scenarios per exam)\n- Passing score: 720 / 1000\n\n## Domain Weightings\n| Domain | Weight |\n|--------|--------|\n| D1: Agentic Architecture & Orchestration | 27% |\n| D2: Tool Design & MCP Integration | 18% |\n| D3: Claude Code Configuration & Workflows | 20% |\n| D4: Prompt Engineering & Structured Output | 20% |\n| D5: Context Management & Reliability | 15% |\n\n## Exam Scenarios\n1. Customer Support Resolution Agent\n2. Code Generation with Claude Code\n3. Multi-Agent Research System\n4. Developer Productivity with Claude\n5. Claude Code for Continuous Integration\n6. Structured Data Extraction\n`;\n","import { readFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nlet quizWidgetHtml: string | null = null;\n\nexport function getQuizWidgetHtml(): string {\n if (!quizWidgetHtml) {\n quizWidgetHtml = readFileSync(resolve(__dirname, '../ui/quiz-widget.html'), 'utf-8');\n }\n return quizWidgetHtml;\n}\n"],"mappings":"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","names":["dbPath","db","fs","path","newEase","nextReviewAt","fs","path","db","db","db","db","db","db","server","db","userConfig","server","db","userConfig","server","db","userConfig","z","db","server","db","userConfig","z","z","server","db","userConfig","z","OPTION_KEYS","server","db","userConfig","path","server","db","userConfig","path","server","db","userConfig","path","fs","path","fileURLToPath","z","__dirname","server","z","server","db","userConfig","db","server","db","userConfig","z","server","db","userConfig","z","server","db","userConfig","z","server","z","z","crypto","db","server","db","userConfig","z","z","shuffleArray","db","server","userConfig","z","db","server","userConfig","server","db","userConfig","z","server","db","userConfig","z","fs","path","fileURLToPath","fileURLToPath","__dirname","__dirname","path","fileURLToPath","server","db","userConfig","fs"]}
|