capstone_build_step
Guide users through 18 progressive steps to complete a certification capstone project, combining quiz questions with hands-on building phases and visual progress tracking.
Instructions
Drive your guided capstone build — quiz, build, and advance through 18 progressive steps.
IMPORTANT:
When presenting quiz questions, use AskUserQuestion with header "Answer" for A/B/C/D selection. If code is in the scenario, add preview fields.
After grading a quiz answer, FIRST show the result (correct/incorrect, explanation) as REGULAR CHAT TEXT so the user can read it. THEN present follow-up options or the next question via AskUserQuestion. Explanations must NOT be hidden behind cards.
When presenting action choices (quiz/build/next), use AskUserQuestion with header "Action".
PROGRESS TRACKING:
On "confirm": Create a TodoWrite checklist with all 18 build steps, all set to "pending".
On "next": Update the completed step to "completed" and the new current step to "in_progress".
This gives the user a visual build progress tracker.
EDGE CASES:
"Other": Answer the question, then re-present the current options via AskUserQuestion.
"Skip": During quiz, treat as moving to the build phase. During build, treat as advancing to next step.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | The build action: confirm, quiz, build, next, status, or abandon |
Implementation Reference
- src/tools/capstone-build-step.ts:335-398 (handler)The handler logic for the 'capstone_build_step' tool, which manages actions like 'confirm', 'quiz', 'build', 'next', 'status', and 'abandon' within the capstone build process.
async ({ action }) => { const userId = userConfig.userId; ensureUser(db, userId); switch (action) { case 'confirm': { const result = handleConfirm(db, userId); if ('isError' in result) return result; const selected = await elicitSingleSelect( server, 'Build confirmed! What would you like to do next?', 'nextAction', [{ value: 'quiz', title: 'Start the first quiz' }], ); return appendSelectedAction(result, selected); } case 'quiz': return handleQuiz(db, userId); case 'build': { const build = getActiveBuild(db, userId); if (!build) { return errorResponse('No active build found.'); } if (build.status !== 'building') { return errorResponse(`Build must be in "building" status. Current status: "${build.status}".`); } const result = handleBuild(db, userId, build); if ('isError' in result) return result; const selected = await elicitSingleSelect( server, 'Build instructions generated. What would you like to do next?', 'nextAction', [ { value: 'next', title: 'Advance to the next step' }, { value: 'status', title: 'Check build progress' }, ], ); return appendSelectedAction(result, selected); } case 'next': { const result = handleNext(db, userId); if ('isError' in result) return result; const selected = await elicitSingleSelect( server, 'Step advanced. What would you like to do next?', 'nextAction', [ { value: 'quiz', title: 'Start this step\'s quiz' }, { value: 'status', title: 'Check build progress' }, ], ); return appendSelectedAction(result, selected); } case 'status': return handleStatus(db, userId); case 'abandon': return handleAbandon(db, userId); } } - src/tools/capstone-build-step.ts:315-399 (registration)The registration of the 'capstone_build_step' tool using server.tool, including the definition of the 'action' input schema.
server.tool( 'capstone_build_step', `Drive your guided capstone build — quiz, build, and advance through 18 progressive steps. IMPORTANT: - When presenting quiz questions, use AskUserQuestion with header "Answer" for A/B/C/D selection. If code is in the scenario, add preview fields. - After grading a quiz answer, FIRST show the result (correct/incorrect, explanation) as REGULAR CHAT TEXT so the user can read it. THEN present follow-up options or the next question via AskUserQuestion. Explanations must NOT be hidden behind cards. - When presenting action choices (quiz/build/next), use AskUserQuestion with header "Action". PROGRESS TRACKING: - On "confirm": Create a TodoWrite checklist with all 18 build steps, all set to "pending". - On "next": Update the completed step to "completed" and the new current step to "in_progress". - This gives the user a visual build progress tracker. EDGE CASES: - "Other": Answer the question, then re-present the current options via AskUserQuestion. - "Skip": During quiz, treat as moving to the build phase. During build, treat as advancing to next step.`, { action: z.enum(ACTIONS).describe('The build action: confirm, quiz, build, next, status, or abandon'), }, async ({ action }) => { const userId = userConfig.userId; ensureUser(db, userId); switch (action) { case 'confirm': { const result = handleConfirm(db, userId); if ('isError' in result) return result; const selected = await elicitSingleSelect( server, 'Build confirmed! What would you like to do next?', 'nextAction', [{ value: 'quiz', title: 'Start the first quiz' }], ); return appendSelectedAction(result, selected); } case 'quiz': return handleQuiz(db, userId); case 'build': { const build = getActiveBuild(db, userId); if (!build) { return errorResponse('No active build found.'); } if (build.status !== 'building') { return errorResponse(`Build must be in "building" status. Current status: "${build.status}".`); } const result = handleBuild(db, userId, build); if ('isError' in result) return result; const selected = await elicitSingleSelect( server, 'Build instructions generated. What would you like to do next?', 'nextAction', [ { value: 'next', title: 'Advance to the next step' }, { value: 'status', title: 'Check build progress' }, ], ); return appendSelectedAction(result, selected); } case 'next': { const result = handleNext(db, userId); if ('isError' in result) return result; const selected = await elicitSingleSelect( server, 'Step advanced. What would you like to do next?', 'nextAction', [ { value: 'quiz', title: 'Start this step\'s quiz' }, { value: 'status', title: 'Check build progress' }, ], ); return appendSelectedAction(result, selected); } case 'status': return handleStatus(db, userId); case 'abandon': return handleAbandon(db, userId); } } );