dsh-doctor: Adding a "Run Code First, Then Answer" Gate for Programming TAs

Preface

When using DSH to act as a TA for programming problems, the two most common failures are not due to the model’s lack of intelligence, but rather the absence of constraints in the workflow. The first is making conclusions based on impression—for example, saying “you wrote the index wrong here”—when the model hasn’t actually run the student’s code. The second is the inability to resist giving the answer: when a student says “just let me see the full code,” the model immediately pastes the correct solution. Neither of these can be stopped by self-discipline alone, nor by a single system prompt.

The approach of buguoshixc/dsh-doctor is to split the response pipeline into tools: attribution must be derived from a verdict based on a real execution; before a reply is sent to the student, it must pass through a gate. If the gate determines that the output can “run to a result” or is “highly similar to the correct solution,” it is blocked. It is not just another prompt template, but a plugin inserted into the DSH workflow.

What is it

The plugin maintainer is buguoshixc, categorized as a workflow, and uses the MIT license (declared as "license": "MIT" in package.json). In a nutshell, it adds a “Diagnostic Mode” agent preset to the DSH desktop client, along with a Python judging core with zero third-party dependencies. This allows the model to run code to gather evidence before answering, using Socratic questioning to guide the student to fix the issues themselves.

The author’s self-definition is clear; it is these things, not those things:

Is Not
DSH plugin (bundle + agent preset) LLM application; does not call any model API
Offline judging core (Python 3.11+ standard library, zero third-party dependencies) Judging cloud service; does not connect to judge0, no internet
Two native tools plus a teaching skill plus a preset Web platform; no frontend, no database, no HTTP service
An answer gate Secure sandbox; local execution only has timeout, memory cap, and best-effort network blocking

The architecture is called “Architecture C”: the model in the session is responsible for generating test cases and the correct solution, while the tools are only responsible for judging. The judging core generates nothing and does not require an API key; it only performs three deterministic tasks—running code, comparing outputs, and blocking answers.

Installation and Enabling

The official installation command comes from the README and docs/INSTALL.md, installed into the desktop profile:

dsh plugin --profile desktop add github:buguoshixc/dsh-doctor

After installation, DSH must be restarted, and then “Diagnostic Mode” must be selected in the preset selector of a new session. There are two equivalent approaches: pasting the prompt from docs/INSTALL-PROMPT.md to the agent, allowing it to self-inspect, install, and verify; or using dsh plugin, which forwards arguments to pnpm in the profile directory. GitHub short name resolution, caching, and lockfile management are handled by pnpm.

Prerequisites are checked according to docs/INSTALL.md:

Dependency Requirement Check Command
DSH Desktop version 0.2.1-rc.3 or higher (below 0.3.0) dsh --version
Python 3.11+, and found by python or python3 python --version
Git Required for installation from GitHub git --version

The version constraints specified in package.json are:

"engines": { "node": ">=22.0.0", "dsh": ">=0.2.1-rc.3 <0.3.0" }

This package has no build steps, consisting of pure ESM and pure Python, and does not require a prepare script. The typical error when Python cannot be found is E_NO_PYTHON. The README suggests using DSH_DOCTOR_PYTHON to hardcode the interpreter’s absolute path, or confirming it is installed in PATH. On Windows, py -3 is the last candidate.

Two Tools

The plugin registers two native tools, with JSON Schemas and implementations in lib/tools.mjs.

doctor_judge: The Sole Arbiter

As long as the student provides code and the problem, it is called first. Drawing conclusions without running it is equivalent to fabricating evidence.

Parameters (from README):

problem        Full problem statement (Markdown, including examples)
code           Full student code
cases          Test case set JSON, e.g. {"func_name":"…","cases":[{"case_id","input","expected","kind"}]}
refs           1~4 correct solution code snippets, cross-verified
func_name / timeout_ms / memory_mb   Optional

It first runs the correct solution for self-verification: if any correct solution does not match expected, it immediately returns verdict=REF_REJECTED, without executing the student’s code or proceeding to attribution. This prevents a situation where the model writing an incorrect correct solution becomes a case of an innocent student being blamed.

The successful path returns verdict, compile, ref_status, failure_distribution, counterexample, category / category_label, confidence, and reason. The README provides an excerpt of a boundary error sample for lc-053-maximum-subarray:

{
  "verdict": "WA",
  "phenotype": "WA",
  "compile": { "passed": true, "errors": "" },
  "ref_status": "trusted",
  "failure_distribution": { "total": 5, "failed": 1, "pattern": "boundary_only" },
  "counterexample": {
    "case_id": "b1",
    "input": [[-3, -2, -5]],
    "expected": -2,
    "actual": 0,
    "kind": "boundary"
  },
  "category": 3,
  "category_label": "边界处理错",
  "confidence": "high",
  "reason": "1/5 条用例失败,失败模式 boundary_only,归类为第 3 类(边界处理错)"
}

The hard-coded case_id, input, expected, and actual in counterexample are the only facts the model can write into its reply. See docs/SCHEMA.md for the full table of fields.

doctor_gate: The Answer Gate

Any reply directed at the student must invoke it before being sent. It has three layers of judgment:

  1. Layer 1 blocks if runnable: the code snippet extracted from the reply is actually executed. If it produces a result, it is judged as block. Syntax checking alone is insufficient—for example, while left < right: is syntactically valid, but it cannot run; it is acceptable pseudo-code.
  2. Layer 2 similarity check to prevent leakage: weighted AST structural similarity (0.55 weight) plus token Jaccard similarity (0.45 weight); >=0.75 is judged as downgrade-to-level2, >=0.60 sets suspect=true to allow passing but with a mark.
  3. Fail-closed: if the content looks like code but cannot be analyzed, it is blocked or downgraded without exception; never treated as “safe”.

The action in the return value is only pass or block, while downgrade-to-level2 falls under recommended_level and reasons. The sample provided in the README:

{
  "action": "block",
  "reason": "layer1 判定为可运行代码(定义了 twoSum)",
  "layer1": { "runnable": true, "detail": "定义了 twoSum" },
  "layer2": { "similarity": 1.0, "ast_sim": 1.0, "token_sim": 1.0, "suspect": true },
  "leaked_fragments": ["def twoSum(nums, target):\n    # 正解 B:哈希表一次遍历,O(n)\n    …"],
  "recommended_level": 1,
  "reasons": ["extract:found_fragment", "layer1:runnable"]
}

“Diagnostic Mode” Preset and Skill Manual

The preset ID is diagnose, and the name is “Diagnostic Mode”. The README provides its declaration method and combination instructions, and also includes an equivalent description in an older format (presets/diagnose/; the instructions state that DSH 0.2.1 and later does not read this directory, keeping it for reference):

Item Content
persona Chinese TA persona; ironclad rule: pass the gate, do not give full code, only use tool evidence, if REF_REJECTED fix before attributing
Declared tool surfaces bash (POSIX) / pwsh (Windows), read/write/edit, glob/grep, skill
Plugin native tools doctor_judge, doctor_gate
Skills doctor, only visible in preset: includeDefaultRoots: false plus package directory
Inherited host tools present, ask_user_question, etc., determined by profile

The real “degree” of control lies in the teaching manual presets/skills/doctor/SKILL.md. The skill is not just decoration; it is part of prompt engineering, designed to ensure the model reads the sequence “run code first, then organize the reply, then pass the gate” in every session. Additionally, the preset does not use prompt variables like {{cwd}}—since DSH 0.2.1, using such variables in the preset persona causes the entire session to fail, so only {{model}} is used.

How to Verify Installation

The verification process provided in docs/INSTALL.md is specific: create a “Diagnostic Mode” session and paste a snippet of code with obvious errors, for example:

def maxSubArray(nums):
    best = 0
    for x in nums:
        best = max(best, best + x)
    return best

The expected model behavior, in order, is: first, generate its own set of test cases and the correct solution, then call doctor_judge; reference specific counterexamples in the reply, ensuring case_id, input, expected value, and actual value are all present; after organizing the reply, call doctor_gate, rewriting and retrying if the action is not pass; the final reply should contain no complete runnable code, but rather one or two guiding questions.

As long as doctor_judge and doctor_gate appear in the “Tool Calls” panel, it indicates the plugin is installed correctly. If the model didn’t call the tools at all, it means the skill wasn’t loaded or the model didn’t read the skill.

To verify the quality of the package itself, the command provided in the README is:

bash scripts/verify.sh

It runs environment self-checks, zero third-party dependency scanning, Python unit tests (93, as stated in the README), Node unit tests (22, as stated in the README, including contract tests using the local real @deepseek-ai/dsh-tools to verify schema), three-question fixture demonstrations (AC/WA/CE/TLE/REF_REJECTED plus the three gating actions), package metadata contracts, and stdout cleanliness, exiting with code 0.

The package’s surface area and dependency relationships are also worth a look. The files whitelist includes lib/, doctor_core/, presets/, locale/, icon.svg, cordis.patch.yml, scripts/verify.sh, and parts of docs/; the three peer dependencies are all marked with optional: true:

"peerDependencies": {
  "@deepseek-ai/dsh-tools": ">=0.2.1-rc.3 <0.3.0",
  "@deepseek-ai/dsh-agent-preset": ">=0.2.1-rc.3 <0.3.0",
  "@deepseek-ai/cordis": ">=4.0.0 <5.0.0"
}

Honest Boundaries

The README lists a few things it does not guarantee; these are not disclaimer-style clichés, but inherent trade-offs of the design.

The correct solution is generated by the model, which is an inherent trade-off of Architecture C. It can only guarantee termination if the correct solution does not match the problem statement examples; it cannot guarantee the correctness of the solution itself. Therefore, doctor_gate is the final line of defense, not the only one.

Local execution is not a secure sandbox. There is only a 5-second wall-clock timeout, 256MB RLIMIT_AS, and best-effort network blocking (replacing socket.socket). On Windows, the resource module does not exist, so memory limits do not take effect, and the memory_limit_not_enforced flag will be present. True isolation requires OS-level sandboxes.

Only Python is supported. The wrappers for C++ and Java, as well as the original platform’s tree-sitter similarity, have not been ported over.

“Must pass the gate first” is prompt engineering, not a mechanism. Tools can block replies that are sent in, but they cannot stop the model from simply not calling them. The way to reduce risk is to hardcode steps in the skill, combined with the first ironclad rule in the persona.

Applicable Scenarios and Notes

The suitable scenarios are clearly stated:

  • TA for programming problems, online judging tutoring, needing workflow constraints of “run then answer”;
  • Want to use deterministic execution evidence to replace impression-based attribution;
  • DSH desktop version is between 0.2.1-rc.3 and 0.3.0, and the local machine has Python 3.11+.

Due to the current information available, the following points require the reader to verify themselves before installation, as the materials do not provide conclusions:

  • Behavior in multi-user concurrent scenarios, not mentioned in materials;
  • Non-Python languages, and execution environments requiring stricter isolation, explicitly stated as unsupported by README;
  • The upper limit of model capability corresponding to correct solution correctness; the plugin itself can only achieve REF_REJECTED termination, cannot guarantee correctness;
  • This plugin runs with the permissions of the current DSH process; the judging core will actually execute the code extracted from the reply. Before installation, you should open the GitHub repository and verify against docs/SCHEMA.md, docs/PLUGIN_API.md, docs/EXTRACTION.md for source code and license. The community directory page is an independent site with no official affiliation to DeepSeek / Sinofin.

Conclusion

The value of dsh-doctor lies not in having another tool, but in embedding the workflow “run code before answering” and “answers are blocked by the gate, not by self-discipline” into the plugin. For those acting as TA for programming problems, the aspect that makes it more robust than simply writing a system prompt is that attribution must include case_id and actual output, and any complete runnable code will definitely be blocked by doctor_gate. The trade-off is that the correct solution is still provided by the model, and local execution is not a security boundary.

Directory: https://www.skillhub.cn/plugins/buguoshixc/dsh-doctor
GitHub: https://github.com/buguoshixc/dsh-doctor

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye