Preface

When troubleshooting bugs, the most time-consuming part is often not the fix itself, but locating the issue. “The bug is definitely in the current code, but I don’t know which segment…” “Clicking authorize returns 405; it’s unclear if it’s the frontend, gateway, or downstream API’s fault…” “It was fine last week; I don’t know which commit broke it.” — When encountering such problems, relying on reading through code or guessing based on experience is inefficient and easily devolves into making random changes here and there.

Binary search is the standard approach for handling such problems: cut the search scope in half each round, and within a few iterations, converge to a specific function, boundary, or commit. dsh-bisect-debug is a DeepSeek Harness (DSH) workflow plugin that solidifies this method into an executable process. DSH’s philosophy is “everything is a plugin”; troubleshooting workflows are provided as plugins, ready to install and use.

What is it

dsh-bisect-debug is maintained by PangYiMing, categorized as a workflow, and licensed under MIT. One-sentence positioning: Use binary search to halve the search scope each round to quickly lock the bug down to a specific function/boundary/commit.

The plugin includes three built-in bisect modes—code bisect, boundary bisect, and commit bisect—along with mode selection guidance, skip conditions, and execution discipline. The core problem it solves is “the bug exists within a certain range, but the specific location is unknown.” The following sections introduce them by mode.

Three Bisect Modes

First, determine which mode to use: Clear good/bad time points → Commit bisect; Cross-layer problem where it’s unclear which layer is at fault → Boundary bisect; Bug confirmed to be in the current code → Code bisect (most common).

Code Bisect

Use Case: The bug is confirmed to be within the current code, and you need to narrow it down to a specific function/component. The prerequisite is having the current code and a reproducible bug.

The process is as follows:

  1. There are N candidates in the scope (function/component/middleware/import);
  2. Comment out the last N/2;
  3. The bug disappears → The root cause is in the commented-out half; continue bisecting the latter half;
  4. The bug persists → The root cause is in the first half; continue bisecting the former half;
  5. Repeat until narrowed down to a specific function or line.

When commenting, preserve the original code and add a bisect-disabled marker for easy restoration:

// [bisect-disabled] <OriginalComponent />
// <OriginalComponent />

Note three points: You cannot randomly comment out modules with dependencies, or you will introduce new errors; after commenting, verify whether the “bug still exists” or not, not “whether there are new errors”; only comment out half per round.

Boundary Bisect

Use Case: Cross-layer problems where it is uncertain whether it is the frontend, backend, or which layer’s fault. The prerequisite is the ability to draw a data flow node graph with at least 3 layers.

The idea is: any bug is “data no longer being correct at some stage.” Verify hop-by-hop along the data flow to find the last stop where the data arrives correctly. Verify from the middle node: if the midpoint is correct, the bug is downstream; if incorrect, the bug is upstream. Verification methods differ across different architectures:

  • HTTP Frontend/Backend: curl directly connects to the backend API, bypassing the frontend;
  • Microservice Chain: curl service by service or check logs;
  • Database: Direct query via DB client;
  • Browser Rendering: DevTools Network + Console;
  • Function Call Chain: Add logs to both the caller and the callee.

The typical combination is to use boundary bisect to determine the layer first, then use code bisect within that layer to determine the function.

Commit Bisect

Use Case: It was working fine before, but you don’t know which commit broke it. The prerequisite is having git history and a clear good/bad commit.

The key to this mode is to solidify the “good/bad judgment” into an exit code script—exit 0 means good, exit 1 means bad, exit 125 means skip—and then hand it over to git bisect run for fully automatic convergence.

Installation and Enablement

The official installation command is as follows:

dsh plugin --profile demo add dsh-bisect-debug
# or install from GitHub
dsh plugin --profile demo add github:PangYiMing/dsh-bisect-debug

Note: The first method corresponds to the npm release, which is marked as “available after publishing to npm” in the documentation. To install it immediately, use the second method to install from GitHub.

Typical Usage

Boundary Bisect in Action: Locating 405 with 3 curls

Real-world case: Clicking authorize returns 405. Send 3 curls along the data flow—MCP login returns 200 (normal), gateway POST returns 405 (abnormal), downstream API returns 422 (normal). Conclusion: The gateway nginx intercepted the POST. It took 3 curls and 0 lines of code changes.

Complete Commit Bisect Process

First, validate the relationship between the good and bad commits, then write the judgment script, and finally hand it over to git bisect run to run automatically:

# 1. Confirm good/bad commits (good inferred from tag/log, don't ask user)
git merge-base --is-ancestor <good> <bad>   # validate good is on bad ancestor chain

# 2. Write judgment script .temp/bisect-judge.sh
npm run build >/dev/null 2>&1 || exit 125
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 30 "http://localhost:8080/")
[ "$code" = "200" ] && exit 0 || exit 1

# 3. Run fully automatic
git bisect start
git bisect bad <bad-commit>
git bisect good <good-commit>
git bisect run bash .temp/bisect-judge.sh

# 4. Cleanup (must do)
git bisect reset

The script first builds, then requests the local service and judges based on the return code: exit 125 on build failure to skip that commit, exit 0 for 200 (good), otherwise exit 1 (bad). git bisect run automatically switches commits based on this and converges to the commit that introduced the bug.

Three points to note for commit bisect: Validate that the base hasn’t expired; upstream merging new files can mislead the bisect; the workspace must be clean before starting; git bisect reset must be executed.

When Not to Use Bisect

The plugin clarifies skip conditions: if it takes no more than 2 steps from the phenomenon to the root cause, do not proceed with bisect. Specifically, these include four scenarios—the compiler has already pointed out the file and line number; the user has explicitly stated the root cause; verification can be done by changing one line; or it is a known version dependency issue.

Bisect is prepared for problems with a large scope but unknown location; when a problem can be seen through at a glance, there is no need to go through the process.

Execution Discipline

The execution discipline attached to the plugin is worth listing separately:

  1. If you have changed ≥2 places in a row without solving it, stop and return to bisecting—this is the strongest anti-laziness rule.
  2. Only change half per round, test before moving to the next half; changing multiple places and testing in one go is prohibited.
  3. Phenomenon first, code last: Use curl/log/ping to confirm the phenomenon and boundaries before touching the code.
  4. Adjust based on the situation when the bug is not reproducible: If it always reproduces, proceed directly to bisecting; if it reproduces intermittently, add diagnostic logs and wait for the next occurrence; if it happens only once, perform maximum log injection and deploy monitoring.

Applicable Scenarios and Notes

Suitable for DSH users who frequently need to locate bugs with a “known rough range but unknown specific location,” especially scenarios where agents execute troubleshooting—the mode selection, skip conditions, and constraints of only changing half per round are written into the workflow, allowing it to constrain agents to follow discipline rather than making random changes.

Security Tip: The plugin runs with the permissions of the current dsh process. It is recommended to check the source code and license before installation. This project is licensed under MIT, and the source code can be viewed directly on GitHub.

Summary

The value of dsh-bisect-debug lies in transforming “locating a bug” from a random guessing game into a standardized process with mode selection, skip conditions, and discipline constraints: bisect when the scope is large, halving it each round until it converges to a specific function/boundary/commit. If you often waste half a day on “not knowing where the bug is,” it is worth trying.

  • GitHub: https://github.com/PangYiMing/dsh-bisect-debug
  • Community Directory: https://www.skillhub.cn/plugins/PangYiMing/dsh-bisect-debug