Skip to content

Releases: Mcd0LUO/dsh-guard-repeat-output

v2.1.6 - 修复短句循环漏判

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 04 Oct 06:23
  • 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 than minSegmentChars (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
    duplicateShare is computed over the segments that survive, discarding the
    repeaters made the collapse look varied instead of repetitive. A real
    collapse looping OK. 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. minSegmentChars is removed, and
    degenerationOnset uses the same rule so detection and pruning agree.
  • lowInfoDupShare 0.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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 27 Sep 10:22

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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 27 Sep 10:16
  • Fixed: a blank modelIncludes silently 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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 26 Sep 15:32
  • 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)

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 26 Sep 15:32

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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 26 Sep 15:32

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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 26 Sep 15:32
  • 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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 26 Sep 15:32
  • 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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 26 Sep 15:32

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

Choose a tag to compare

@Mcd0LUO Mcd0LUO released this 26 Sep 15:32

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.