hongdougao111/dsh-bagu: A gate before AI speaks to the outside

Preface

After agents are integrated into chat, comments, commits, PRs, and documentation, a common problem arises: the text they write looks like it was written by a human, but it smells like a template. The same agent writes “Thanks for sharing, learned a lot” in comments, “Optimized code structure, improved maintainability” in commits, and “// Initialize counter” in comments. Humans find this content uncomfortable to see, but if this agent is on the automatic reply, release, or review chain, these template-like tones will be sent out unchanged.

The existing approach is post-hoc auditing: either humans manually review the output before blocking, or adding a few more lines to the prompt saying “Don’t use clichés.” The former is unreliable, and the latter is also unreliable—the “template flavor” is recognized by its shape via rules, not eliminated by changing wording in a single generation.

dsh-bagu moves this to before sending: before AI speaks to the outside, it passes through a local regex filter. If it passes, it is sent; if it doesn’t, it is bounced back with a suggestion on how to change. The judgment does not call the model; the overhead is fixed.

What is it

hongdougao111/dsh-bagu, by hongdougao111, is a DSH plugin, category admin-security. A one-sentence positioning is “a gate before AI speaks to the outside,” covering scenarios where AI writes and humans read, such as chat, comments, emails, commits, PRs, documentation, and code comments.

The so-called “passing through a gate” means handing the text to bagu_guard for checking before sending. If it passes, it returns OK; if it fails, it is bounced back with a suggestion on the modification direction.

The only criterion is: If you say this sentence with a different person, does it still make sense?

"Sold out cards, wrote randomly"              → Can send (couldn't make one up)
"This video is really good"                  → Block (anyone can say it)
"No longer clearing entered phone number on login failure"   → Can send (specific to a line)
"Optimized code structure, improved maintainability"     → Block (which line? didn't say)

Rule Structure: Three Layers

Rules are built in three layers, becoming more specific as you go down. The first two layers are scenario-agnostic, and the third layer grows from each scenario.

The first layer is general, divided into three types: Empty Action (says an action but not what was done, e.g., “Optimized code structure”, “Fixed a few known issues”), Empty Adjectives (words that can be pasted onto any product, e.g., “Advanced technical architecture”), and Universal Phrases (phrases that flow anywhere, e.g., “With the development of AI”).

The second layer is clichés, divided into three types: Template Sentences (“I recognize this one”, “This fish noted it”), Chicken Soup Slogans (“May your path be smooth”), and Academic Tone (“Learned a lot”, “Very practical”).

The third layer is scenarios; README provides git and code comments as two groups:

feat: 优化了用户模块的代码结构          → Empty Action
## 概述 / ## 改动 / ## 影响            → PR template skeleton
整体实现思路清晰,建议后续优化          → review empty talk
感谢反馈!这个问题我们已经记录          → issue service tone

// 初始化计数器                        → Block
// 这里之所以要排序,是因为下游依赖顺序稳定的分页   → Can send

The criterion for the comment line is: Comments should explain why, not explain the what already expressed by the code itself. Source is beagle’s style-criteria and voku/code-slop’s comments-hygiene.

Test Data

The test table given in README lists 8 rows of results, scripts are in tools/ and can be run directly:

Test Sample Result
Tieba Real Humans (Sunba + Vba original) 68 items False block 0
Bilibili Comments (Catgirl draft + Fish Gangster hot) 50 items False block 0
Global Scenarios (18 scenes × 2 items) 36 items Miss 0, False block 0
Real Human Quotes (DSH + Chat) 51 items False block 0
Git Real Humans (Commit + PR + Review) 28 items False block 0
AI Clichés (Service tone + Parallelism + Empty praise + Template) 35 items Blocked 35 (100%)
Real Scenarios 25 items Miss 0, False block 0
Evasion (Intentional skin change) 10 types Blocked 6 (60%)

Reproduction commands:

node tools/tieba-real.mjs   # Tieba Real Humans 68 items (Sunba, Vba original)
node tools/all-scenes.mjs   # 18 scenarios, 36 items
node tools/falserate.mjs    # Real Humans 51 items
node tools/git-false.mjs    # Git Real Humans 28 items
node tools/missrate.mjs     # AI Clichés 35 items
node tools/evasion.mjs      # Evasion
node tools/audit.mjs        # Real Scenarios 25 items

The batch of 68 items from Tieba is worth a special mention. Real human speech in Sunba and Vba contains question marks, three-part parallelism, counter-attacks after repetition, direct cursing, single-word replies, and meme integration. According to “Cliché Rules,” these shapes are prone to false positives, but this batch had zero false blocks—the rules did not treat these real human speaking styles as template sentences.

Writing out the sources and phrasing styles of this corpus is a key sample for judging whether these rules will “injure real humans.”

Citation vs. Usage

This is the hardest point to judge for this gate: when a sentence appears in quotes, is being criticized, or is being used as an example for commentary, it should not be blocked.

"Comments are full of 'I noted it'"        → Discussing this sentence, not using it → Pass
"I noted it"                                → Directly used → Block
"Don't just say 'benefited a lot'"             → Criticizing, not using → Pass
"Benefited a lot"                        → Really praising → Block

The criteria have four points: Content in quotes does not participate in judgment; Clichés preceded by negative words (don’t/avoid) indicate criticism; Clichés preceded by pronouns (this sentence/this/this line) indicate referring to previous text; Clichés followed by evaluative words (thunder/counter-example/homework) indicate using it as an example.

What it can’t stop

Of the 10 evasion techniques in the adversarial test, 6 were blocked, and the remaining 4 are known boundaries:

  • Synonym replacement—‘Features are so powerful, easy to use’, words changed but shape not changed
  • Switch to English—English only did leeway words, sentence structure not done
  • Add swearing to disguise—‘Really fucking good’, swearing drowned out the evaluative word
  • Remove grouping markers—‘Goals are clear, tasks are split’

README puts it bluntly: Rules can only recognize shape, not “whether this sentence is really true.” This is a tourniquet, not a cure.

Long Text vs. Short Sentences

Text over 300 characters is not skipped; long emails, weekly reports, and long PRs will also be cliché. However, the threshold for long text is different: the same signal must appear more than twice to count; appearing once will not be rejected. Otherwise, an occasional “optimized” in long text would be rejected as a whole.

Short sentences are also handled specially. Chat replies of 20-30 words are normal; density indicators have too small a denominator at this length, so below 60 characters, switch to absolute counting, not density, looking at what was hit.

"This isn't a technical problem, but a cognitive problem."   → Block
"Sold out cards, wrote randomly"               → Can send

Usage

The default mode is guarding; call once, returns OK if pass, returns a line of less than 40 characters with modification direction if blocked:

bagu_guard({ text: "这条我认!首先态度要正,其次内容要实,最后要持续更新。" })
→ "改:模板三连 · 直接说事,不用「首先其次最后」"

bagu_guard({ text: "登录失败时不再清空已填的手机号" })
→ "OK"

The output budget is clearly written: 2 characters for pass, less than 40 for block. Ranked by severity, only report the first one—README’s reason is that if three are reported, the agent will pick the lightest one to change.

Two other modes:

bagu_guard({ text, mode: 'report' })    // Detailed report, for humans
bagu_guard({ text, mode: 'ask' })       // Only questions

Meme Library: Optional, Default Off

The plugin comes with a meme library module, data from MemeWiki public API. It judges another thing—“Is this meme outdated” or “What does this word mean”—which is not the same as “Anyone can say it,” so it is off by default; you need to turn it on in the settings page.

After turning it on, two things: bagu_meme({ q }) can query the meaning of a word; bagu_guard result will append “Meme: XXX,” does not change judgment. The guard itself does not depend on the meme library; the video opening lines derived from it (“Pay attention”, “This man is called Xiaoshuai”, “Not much to say”, “One-click triad”) are already written into the VIDEO_STOCK rule in the rules, whether the meme library is on or off does not affect it.

Data file is in data/memes.json, 120 entries with full anchors (59KB), full set is 3180 entries.

node tools/fetch-memes.mjs data/memes.json 20    # Fetch meme library

Installation and Enable

dsh plugin --profile web add dsh-bagu

After installing, restart dsh; you can see it in “Settings → Cliché Detection.”

Settings Page

The settings page has four items: Block or not (Master switch), How strict (Normal only blocks hard signals, strict blocks even dashes), Hint section (Turn off to keep only tool, don’t stuff text into system prompts), Test a snippet (Five samples, see if they pass on the spot).

Runtime Overhead

Judgment is run entirely in local regex, no model calls. Fixed overhead:

Item Size
System prompt injection 31 chars
Tool description (1) 54 chars
Guard output 2 chars (pass) / <40 chars (block)

The system prompt is only one sentence: “If you want to send it out, pass bagu_guard first. If blocked, change it, don’t hard send it.”

Development and License

npm test    # 70 unit tests

main in package.json is lib/index.js, Node version requires >=18, build artifacts include lib, test, data, client.js, dsh-plugin.json, cordis.patch.yml. License MIT.

Regarding data sources, README gives four types: two-round comparative experiments (1169 articles, 5.2 million words), density tests of 100k real comments and 2180 AI comments, sloplint scoring formula, beagle and code-slop comment criteria.

Suitable Scenarios and Notes

Suitable for people who are already using DSH to run agents for automatic reply, release, review, and documentation writing, who don’t want template-like tones sent out unchanged, and hope to check locally with controllable overhead without depending on model calls.

Two points need personal judgment. First, the plugin runs with the permissions of the current dsh process, can read all contexts the process can read; review dsh-bagu source code and cordis.patch.yml before installing. The license is MIT, but the license solves if you can use it, not if something will go wrong. Second, its judgment is regex shape matching, not semantic understanding—synonym replacement, English sentence structures, swearing disguise are indeed bypassed in adversarial tests. Before putting it in your automatic sending chain, use “Test a Snippet” in the settings page to run through your own real corpus first.

Conclusion

The value of this solution lies in moving “AI flavor” from prompt mysticism to reproducible local checks, and the risk of false positives on real humans was calibrated with real human corpus from Tieba, Bilibili, etc. Its positioning is honest: it’s a tourniquet, not a cure.

Directory: https://www.skillhub.cn/plugins/hongdougao111/dsh-bagu

GitHub: https://github.com/hongdougao111/dsh-bagu

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

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

Xiaoye