Repository navigation
CLI вокруг цикла урока и MCP-сервер softpractice mcp - #5
Merged
Merged
Conversation
ErrLoginRequired and ErrProjectNotLinked let a caller tell a state a person must fix from other failures without matching messages; the messages are unchanged. AuthorizedPoll returns the status and Retry-After of a pending 202 answer, and of an error answer such as 429. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9oUWMHw3ZCHpfmoBGcgeF
status, submit, submission show, and update now call learnerUseCases, which return results instead of printing them, so a later `softpractice mcp` can call the same operations. Command output is unchanged. status --format json gains additive fields: assignment.title, lesson_version_update while a newer lesson version is published, and latest_submission.evaluation_status once the evaluation is terminal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9oUWMHw3ZCHpfmoBGcgeF
`softpractice evaluation [--wait] [--timeout]` reads
/v1/submissions/{id}/evaluation, waits at the Retry-After interval the
server sets, and reports a superseded evaluation and a wait that ends
before the result as separate outcomes with exit codes 4 and 3.
`softpractice assignment show` prints the assignment text of the lesson
version the folder holds and its theory material.
Both print JSON in the existing contract_version/kind format and, in JSON
mode, a softpractice.error document that says when a login or a linked
project is required. machineReviewFeedback keeps the reviewer's
recommendations and other free text out of this output by default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9oUWMHw3ZCHpfmoBGcgeF
The CLI is not released yet, so there is no v2 consumer to keep. v2 passed the whole evaluation projection through, including the reviewer's recommendations and the defense questions; `--format json` is now the only machine format. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9oUWMHw3ZCHpfmoBGcgeF
…version `softpractice evaluation` now prints what the checks and the reviewer found and why: counterexamples, the review summary, the rubric with rationales, and each finding's observation and risk. The reviewer's directions and the counterexamples' next steps are printed only with --directions; defaultReviewFeedback keeps them out otherwise. The reviewer's questions are never printed, only their number. The text output is Markdown so it reads in a terminal and renders in an agent's chat. The JSON documents lose contract_version, since the CLI has no released consumers to version for, and the evaluation document carries one `result` object instead of two overlapping ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9oUWMHw3ZCHpfmoBGcgeF
Commands follow what a learner does: task, material (--lesson for an
earlier lesson), hint, submit --wait, result, submissions, and
open task|material|result. They replace assignment show, evaluation,
submission show, and submission download (now submissions download).
status ends with the next step, and lists next_actions in JSON: apply
the update, commit, submit, wait, read the result, or answer the
reviewer's questions on the result page. A new commit after a submission
is detected from the submission's commit_sha.
The reviewer's questions and opening the next hint stay on the site:
result, status, and hint give the page link. The CLI never prints the
questions' text.
Every JSON-capable command takes --json and prints a softpractice.error
document on failure. Invalid arguments exit with code 2. open no longer
links to /workspaces/{id}, which the web app does not serve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9oUWMHw3ZCHpfmoBGcgeF
- With --json, every error is a softpractice.error document, including an invalid command line (code usage): the commands now report errors in one deferred place and read --json from the raw arguments. - Declining the submit confirmation is error code declined (exit 1) instead of a silent success with empty stdout. - status next steps: practicum_completed with the completion page for a completed workspace, workspace_inactive for an archived one, retry_evaluation with the result page after a technical failure, resubmit after a superseded evaluation, and stash_changes before apply_update on a dirty tree. - A malformed --id is a usage error (exit 2) for result and submissions download. - open accepts the page after the flags, and open result falls back to the accepted predecessor like result does. - submit --wait accepts --directions. - Drop the unused evaluation projection built by normalizeSubmissionResponse. - Tests for JSON usage errors, declined submit, submit --json receipt, rate limits without an answer, cancellation while waiting, token refresh during polling, and the new next steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Xxe94ZEJnVQm1pzvTR1aK
- Evaluation projects the evaluation at a requested detail itself; the raw API projection, with directions and reviewer questions, no longer leaves the use case. - update is split into PrepareUpdate, which checks everything and lists the file operations without touching the folder, and ApplyUpdate, which refuses when HEAD or the working tree moved since the plan was made. - CheckPublished runs the public checks only when .softpractice/checks.json matches the configuration the server publishes for the folder's lesson. The CLI behaves as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XKQjpw1FmuSnc8k4EtFspp
`softpractice mcp [--project DIR]` serves the lesson loop to Claude Code, Codex, Claude Desktop and other MCP clients through the same use cases as the CLI: status, task, material, hints, check, submit, result, submissions and update, plus the task and material as resources. - Tool names, descriptions and schemas are in English for the model; messages for the person follow the CLI language, Russian when none is configured, since the course content is Russian. - submit and update ask the person to confirm with a preview (commit and size; the add/replace/delete list). The confirmation is a multi round-trip tool result, so it works on protocol 2026-07-28 and, through the SDK, as elicitation/create on older clients. A client without elicitation gets confirmation_unavailable; nothing is done. The retry re-prepares the action and refuses when it changed after the person saw it; the state it carries is signed by the server process. - Evaluations are always projected without directions, and the reviewer's questions are never returned; there is no parameter for either. Hints are read-only. check runs only the configuration the server publishes. - Errors are isError results with a stable code and what the person has to do. The server never starts a sign-in, and only JSON-RPC reaches stdout. - status next_actions name the tool to call instead of a CLI command. Uses github.com/modelcontextprotocol/go-sdk v1.8.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XKQjpw1FmuSnc8k4EtFspp
How to connect it to Claude Code, Codex and Claude Desktop, the tools and resources it serves, what it leaves to the learner (confirmation, directions, reviewer questions, hints, unpublished checks), the error format, and the language of its messages. The npm README is kept equal to README.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XKQjpw1FmuSnc8k4EtFspp
On Windows the system locale reports the display language, so the MCP server correctly answers in English there instead of the Russian default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XKQjpw1FmuSnc8k4EtFspp
After a commit git may start a detached gc or maintenance process that keeps writing to .git after the test returns, so t.TempDir cleanup fails with "directory not empty" (seen on the ubuntu runner, git 2.55). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XKQjpw1FmuSnc8k4EtFspp
60 seconds equals Codex's default tool call timeout, so a suggested wait could time out the call before the result arrives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XKQjpw1FmuSnc8k4EtFspp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что сделано
CLI перестроен вокруг цикла урока, чтобы по нему было удобно работать и из терминала, и из Claude Code / Codex. Поверх общего слоя use case добавлен локальный MCP-сервер
softpractice mcp. Обратная совместимость не сохраняется: у CLI ещё нет выпущенных версий с внешними потребителями.Команды
status [--json]next_actions: [{code, command?, url?}]task [--json]material [--lesson ID] [--json]--lessonhint [--json]submit [--wait] [--timeout] [--json]--waitсразу ждёт результатresult [--id] [--wait] [--timeout] [--directions] [--json]submissions [--json],submissions download --id/iteration), скачивание ревизииopen [task|material|result]mcp [--project DIR]Эти команды заменяют
assignment show,evaluation,submission show,submission downloadи--format json. Дляjson-v2иcontract_versionзамены нет.Следующий шаг в
statusВозможные шаги:
apply_update→update;commit_changes;submit→submit --wait;wait_result→result --wait;read_result→result;answer_questions→ ссылка на страницу результата;update_lesson_version. Новый коммит после отправки определяется сравнениемHEADсrevision.commit_shaизGET /v1/submissions/{id}.Что выводит
result--directions:directionзамечаний иnext_stepконтрпримеров. Без флага выводитсяdirections_hidden: trueи строка с подсказкой про флаг.uncertain,questions_answerable: true),resultиstatusпишут «Ответьте на странице результата: <ссылка>».defaultReviewFeedbackвcmd/softpractice/feedback.go.Ожидание, ошибки, коды выхода
202пауза ровно поRetry-After;429сRetry-Afterво время ожидания тоже выжидается.409 evaluation_superseded— отдельный исход.0— готово,1— ошибка,2— неверные аргументы,3— проверка ещё не готова (в том числе истекло время ожидания),4— проверка заменена.softpractice.errorс кодомusage,login_required,project_not_linked,not_git_repository,checks_not_published,api_error,cancelledилиerror. Уsubmit --jsonвсё, что адресовано человеку (превью, проверки, подтверждение), идёт в stderr. Процедуру входа (device flow) CLI сам никогда не запускает.openбез отправок вёл на/workspaces/{id}— такой страницы в вебе нет.Общий слой use case
cmd/softpractice/usecase.go,learnerUseCases:Status,Lesson,Task,Material,Hints,Submissions,SubmittedCommit,PrepareSubmission/SendSubmission,PrepareUpdate/ApplyUpdate,CheckPublished,Evaluation,LatestSubmission. Use case ничего не пишут в stdout. ВlearnercliдобавленыErrLoginRequired,ErrProjectNotLinkedиAuthorizedPoll, который возвращаетRetry-After.Evaluationсам строит проекцию на запрошенном уровне детализации; сырая проекция API (сdirection,next_step,defense_questions) из use case не выходит.PrepareUpdateделает все проверкиupdateи возвращает план (вид обновления, откуда → куда, операции add/replace/delete), ничего не меняя.ApplyUpdateотказывает, еслиHEADили рабочее дерево сдвинулись после подготовки.update_plan.go.CheckPublishedзапускает публичные проверки, только если.softpractice/checks.jsonсовпадает с конфигурацией, которую сервер публикует для урока папки. CLI-командаcheckне изменилась.softpractice mcp
cmd/softpractice/mcp.go, SDKgithub.com/modelcontextprotocol/go-sdkv1.8.0 (Apache-2.0 с переходом с MIT,go 1.25). stdio черезIOTransportповерх stdin/stdout изrun().statusStatus;next_actionsсодержатtool/argumentsвместо CLI-командtaskTaskmateriallesson_id?MaterialhintsHints(только открытые)checkCheckPublished;{passed, failure, output, truncated}submitwait_seconds0–600PrepareSubmission→ подтверждение →SendSubmission→Evaluationresultsubmission_id?,wait_secondsLatestSubmission+EvaluationsubmissionsSubmissionsupdatePrepareUpdate→ подтверждение →ApplyUpdateResources:
softpractice://lesson/task,softpractice://lesson/material(Markdown). Prompts нет.instructionsсервера и коды ошибок — на английском (их читает модель). Сообщения для человека (подтверждение, ошибки, progress) — на языке CLI; если язык нигде не задан (--lang,SOFTPRACTICE_LANGUAGE,set lang, локаль), MCP-сервер говорит по-русски, на языке курса.instructionsсообщают модели, что материалы курса на русском.submitиupdate. В протоколе 2026-07-28 сервер не может слатьelicitation/createпосреди вызова инструмента, поэтому подтверждение сделано как multi round-trip результат (SEP-2322): первый вызов возвращаетInputRequests.confirmс превью (урок, commit, файлы и размер, предупреждения о чувствительных файлах / список add/replace/delete), клиент спрашивает человека и повторяет вызов. Старым клиентам SDK сам отправляетelicitation/create. Состояние подписано HMAC-ключом процесса; при повторе действие готовится заново и отклоняется сchanged_since_confirmation, если отличается от показанного. Клиент без elicitation получаетconfirmation_unavailable— ничего не делается.mcpReviewFeedback = feedbackWithoutDirections, параметра нет; текст вопросов рецензента не отдаётся; подсказки не открываются;login/logout, retry,starter/restore,set,openне входят. Локальные проверки внутри MCP-submitне запускаются (local_checks: "not_run"), для этого естьcheck.wait_secondsограничивает ожидание, паузы — поRetry-After; на каждом pending-ответе отправляется progress-уведомление, если клиент передал токен.isErrorс JSON{"error": {code, message, action?, http_status?, api_code?, support_id?}};actionговорит человеку, что сделать (softpractice login,--project,softpractice check).Ограничение: это границы инструментов MCP. Агент с доступом к shell может вызвать
softpractice result --directionsилиsubmit --yesсам; настоящая граница возможна только на сервере (см. ниже).Тесты
Покрыто фейковым API (
httptest):202+Retry-After(проверяются фактические паузы),429,409, истечение таймаута;401и отсутствие входа — без токенов в выводе; нет связанного проекта или git-репозитория — для всех новых команд; неверные аргументы дают usage-ошибку;result: что показывается без--directionsи с ним; текст вопросов не выводится никогда; ссылка для ответа на вопросы;taskиmaterialберут версию урока из папки,material --lesson,hint,submit --wait --json,open task;HEAD;direction,next_step,defense_questionsне встречаются ни вresult, ни вsubmitс ожиданием; подтверждение, отказ и принятие на протоколах 2026-07-28 и 2025-11-25; отказ без elicitation;changed_since_confirmation; превьюupdate;login_requiredбез токенов и без device flow;run(["mcp"])через stdio пишет в stdout только JSON-RPC.Прогнаны
go test ./...(и-raceдля новых тестов),go vet,gofmt, сборка под linux/windows/darwin. Два теста границ проверены мутациями: включённые directions и снятая проверка elicitation их валят.Решения
explainнет.AGENTS.md/CLAUDE.mdв стартовых проектах — отдельной итерацией.Пробелы и расхождения в API (monorepo не менялся)
POST /evaluation/retryпомечен как только-веб, а обработчикretryEvaluationиспользуетauthenticate(..., ScopeWorkspaceRead)и принимает CLI-токен; защищает толькоrequireOrigin, а заголовокOriginвне браузера подделывается. Токен с правом чтения может запустить изменяющее действие.current-assignmentуlatest_submissionнетevaluation_statusиcommit_sha, поэтомуstatusделает до двух дополнительных запросов./assignments/{id}?version=N,…/material,/submissions/{id}/result) CLI собирает сам; в API их нет.404для материала нельзя отличить «материала нет» от «не найдено». УReviewFeedbackItemнет категории.directionработает только на стороне клиента и не является границей безопасности: API отдаёт полную проекцию CLI-токену. Настоящая граница — не отдаватьdirection/defense_questionsтокену CLI или вынести их в отдельный scope.Не проверено
Реальный device flow, локальный gateway
https://local.softpractice.ru/, ответы реального API: устаревшая версия урока, отсутствующий материал,material --lessonдля прошлого урока,prepared-hintsи/iterationпо CLI-токену. MCP-сервер проверен in-process клиентом SDK и сырым JSON-RPC через stdio, но не в самих Claude Code, Codex и Claude Desktop: поддержка elicitation в каждом из них не проверялась.🤖 Generated with Claude Code
https://claude.ai/code/session_01XKQjpw1FmuSnc8k4EtFspp