Repository navigation
Releases: Mcd0LUO/dsh-guard-repeat-output
Release list
v2.1.6 - 修复短句循环漏判
- Fixed: short-sentence repetition collapse stopped being detected, so the
guard no longer discarded the bad attempt or re-issued the call. The detector
dropped every segment shorter thanminSegmentChars(12), intending to discard
punctuation noise. When the degenerate pattern migrated from long clauses
(Let me write the call.) to short ones (OK./Let me run.), every segment
of a collapse fell under that floor. The damage was worse than a miss: because
duplicateShareis computed over the segments that survive, discarding the
repeaters made the collapse look varied instead of repetitive. A real
collapse loopingOK.44 times scored a duplicate share of 0.60 and never
convicted. Segments are now kept whenever they carry a letter or digit, however
short; only bare punctuation is dropped.minSegmentCharsis removed, and
degenerationOnsetuses the same rule so detection and pruning agree. lowInfoDupShare0.85 → 0.80. With the corrected segmentation the share is
measured over the same segment set the phrase leg uses; 0.85 was tuned against
the old, length-filtered statistic.- Measured, not assumed. On the frozen corpus (62 real collapses, 1708 real
legitimate reasoning parts) plus 146 collapses captured live under the new
pattern: the fixed detector convicts 62/62, 146/146, 0/1708 false
positives. The previous build caught 0/146 of the live collapses. - Production impact: 144 collapses in a single session between 2026-09-29 and
2026-10-02 were silently allowed through (22 on 09-30, 106 on 10-01, 15 on
10-02), which is why the guard log goes quiet from 09-29 onward.
npm: npm i dsh-guard-repeat-output@2.1.6
2.1.5 — Readable Chinese README; corrected counts
Documentation only; no behavioural change.
- The Chinese README was rewritten for readability. The first pass was a literal
translation of the English text, which left it dense and full of jargon a Chinese
reader had to decode. It now leads with a plain-language summary, explains each
mechanism in ordinary wording, and drops detail that only matters when editing the
source. - Corrected two numbers in the English README. The incident table cited
"let me write the call"× 1,951; the actual count is 1,952. The quoted phrases
are now reproduced exactly as they appear in the captured text (capitalised, with the
trailing period), so the counts can be verified by search rather than guessed at. - Both READMEs now state the measured production result — 12 real collapses caught, all
12 recovered, none of the discarded text reached session history.
2.1.4 — Blank scope fix; Chinese README
- Fixed: a blank
modelIncludessilently widened the scope to every model.
[] deliberately means "every model", but [' '] — a list the caller clearly meant
to narrow — was filtered to empty and therefore matched everything too. That is the
opposite of the intent and the dangerous direction, because every threshold is
calibrated on DeepSeek output alone.
A non-empty list whose entries all normalize away is now rejected with an error that
names the empty-array alternative. truncateChannels was checked for the same class of
bug and is safe: it matches exactly, so an unmatched entry disables truncation rather
than enabling it everywhere.
- Chinese README (
README.zh-CN.md) with a language switcher in both files. verify/config.mjs— 23 checks covering scope validation, numeric ranges and boolean
flags, so a future edit cannot quietly reintroduce the fail-open.
2.1.3 — Repository metadata; latest
- Package metadata completed. , , and
were absent, so the npm page carried no link back to this repository. They were
added once before and then dropped when was rewritten for 1.2.0 —
which is why the fix is called out rather than assumed. - The description was stale. It still described v1's behaviour ("truncates the
stream at the collapse point"); v2 discards the whole attempt and retries, and
the package now also strips garbage code points and can decontaminate a session
retroactively. All three are named now.
No behavioural change.
2.1.2 — Activation line (includes 2.1.1)
This release and differ by one line; both are described here.
2.1.1 — the plugin now logs one activation line on mount. It was silent
before, so a mounted plugin and an unmounted one looked identical in the journal,
making "is it actually running?" unanswerable at exactly the moment it matters.
2.1.2 — that line now goes to instead of .
The 2.1.1 line was written through and never appeared: the harness
does not surface to the service journal. Confirmed on a live deploy,
and is what the sibling plugins use for their own startup lines.
2.1.0 — Garbage sanitization and retroactive cleanup
Ported the two capabilities of the earlier so that
replacing it with this package loses nothing.
Note: was published but never had its own commit pushed to this
repository, so there is no tag. Its change — removing effort
perturbation, so the retry re-issues the request unchanged — is included in
this release. Measured before removing it: of 16 real convictions, 6 of the 9
sessions that were successfully lowered collapsed again anyway (67%), and it
cost 8 dead turns from adapters rejecting a rung the model does not declare.
- Blacklist sanitization (). Control characters, U+FFFD,
zero-width filler and lone surrogates are stripped from every delta before it is
forwarded, so they can never reach the session log. A dense burst (an unbroken
run of , or a share of one delta) is treated as
collapse evidence in its own right; a single stray U+FFFD is a decoding hiccup
and is cleaned silently. - Retroactive cleanup (, ). Scans the session
log for degenerate reasoning that is already persisted and shadows it with a
short note, so the next request stops replaying it. Nothing is deleted — the
append-only log keeps the original bytes. A message that owns tool calls is
skipped rather than shadowed, because shadowing it would orphan its
replies. - The offline scan reuses the live detector rather than a second
implementation, so the two can never disagree about what "degenerate" means. - includes , so the new modules ship.
1.3.0 — Lowered rung lasts one turn; necessity measured
- The lowered rung now lasts exactly one turn. Recovery moved from "the next
request" to the turn boundary: within the collapsing turn the lowered rung
stands (a long turn cannot thrash back to the effort that just collapsed), and
the first request of the next turn restores the original effort. - Measured whether the lowering is actually necessary — see
.
Across 16 real convictions: 9 were lowered and all 9 resolved; 7 were rejected
lowerings and 3 of those died. Separately, 6 of the 9 successfully-lowered
sessions collapsed again later (67%), so the discard-and-regenerate is doing
most of the work and the lowering is a cheap perturbation rather than a cure.
1.2.0 — Ladder derived from the adapter; lowering is restored
- The perturbation ladder is now derived from the adapter. The guard asks the
provider which reasoning efforts the exact model declares and steps down that
list, instead of trusting a hard-coded ladder. A rung the model does not offer
throws and turns a caught collapse into a dead
turn, so this removes a class of failure rather than just a value. - The lowered effort is restored. A perturbation is written into
and every later request derives from it, so without an explicit
restore one collapse left the session on the lowered rung permanently. A live
session dropped to and ran its remaining 12 steps there. Recovery also
defers to any externally chosen effort. - Fallback ladder no longer names . The observed DeepSeek adapter
declares ///; was never valid for it. The
fallback is now , strongest-first. - Corrected a source comment that claimed a perturbed config "is never persisted
as the session's route". The loop re-logs whenever the config
changes, so it is persisted — which is why recovery is needed.
1.1.0 — Cross-platform support
Cross-platform support. The plugin previously assumed a Linux host in five
places; all are fixed.
- Portable configured paths. and accept , ,
a relative path (resolved under the harness home), or any platform's absolute
path. The shipped defaults are now relative instead of Linux absolute paths. - No more string-concatenated paths. used , which
produced mixed separators on Windows; it now uses . - Absolute paths are never silently rebased. A Windows path read on Linux
(or vice versa) is passed through rather than rewritten under the harness home. - Log directories are created when missing. does not create
parents on any platform, so a fresh install silently lost every record. - Sidecar file names are sanitized. Session/agent ids could contribute
characters that are illegal on some platforms, including reserved device names
such as and .
1.0.0 — Initial release
Initial release.
Host-side guard that detects degenerate repetition collapse in a streaming model
reply, truncates the stream at the collapse point, and drives the agent to
continue from there.
Install
added 1 package, and removed 1 package in 2s
Mount — the package ships a Cordis patch layer (), so adding
the dependency is enough for a bundle-based profile.