Skip to content

[scanner] Gate proposal: ECMA-48 conformance test for stripTerminalEscapes (3rd recogniser gap: 8-bit ST U+009C over-strips) #418

Closed

Description

@hivecommons-hive

Summary

Three stripTerminalEscapes recogniser gaps have now been found one at a time in src/sanitize.ts, each fixed by adding one more regex and one more pinned assertion:

  1. [quality] sanitize.ts: two-byte ESC rule misses Fs/Fp finals (ESC c, ESC 7, ESC 8) its docblock claims to cover #414 — Fs/Fp two-byte finals (ESC c, ESC 7, ESC 8) leaked past the two-byte rule (fixed in 🐛 fix: strip Fs/Fp finals in the generic two-byte ESC rule #415).

  2. Review backlog (correctness): nF (intermediate-byte) ESC sequences such as ESC # 8 still leak their payload #416 — nF intermediate-byte sequences (ESC # 8, ESC % G) leaked their payload (fixed in 🐛 fix(sanitize): strip nF intermediate-byte ESC sequences #417).

  3. New, third instance (not filed separately per the three-of-a-class rule): the string terminator recognised by replaceControlStrings is only BEL or 7-bit ST (ESC \). The 8-bit ST U+009C that stringifyForTerminal's docblock already acknowledges emulators honour is not a terminator. An OSC/APC/PM closed by U+009C is therefore treated as unterminated, and the span runs to the next BEL / ESC \ anywhere later in the buffer — swallowing legitimate text in between.

    Reproduction against the current replaceControlStrings logic (10e3012):

    input : "\x1b]0;title\x9c I cannot run the tests \x1b]2;x\x07 tail"
    output: "  tail"
    

    For watcher.ts this is an evasion vector, not just a cosmetic leak: an agent whose pane emits a U+009C-terminated OSC (title set) followed later by a BEL-terminated one hides every rationalisation line between them from pattern matching. For sanitizeForTerminal it drops operator-visible text.

Why a gate rather than a fourth one-off fix

Same root cause each time: the recogniser is an ad-hoc chain of regexes that is extended whenever someone remembers one more ECMA-48 form, and the tests (#411) pin only the forms already known. Nothing in CI checks the chain against the actual ECMA-48 / VT grammar, so the next unknown form (8-bit CSI U+009B parameters, SOS ESC X, ESC k title strings…) will arrive the same way.

Proposed gate (accept or decline):

  • Add a reference-parser conformance test to src/sanitize.test.ts that drives stripTerminalEscapes with a generated corpus from a small ECMA-48 state machine (the Paul Williams VT500 parser states: ESC intermediates, CSI params/intermediates/finals, OSC/DCS/APC/PM/SOS strings terminated by BEL, 7-bit ST and 8-bit ST) and asserts (a) every generated sequence is fully removed and (b) the surrounding plain text is preserved byte-for-byte. Runs in the existing build-and-test job in ci.yml; no new tool required.
  • Optionally make mutation.yml fail (thresholds.break) for src/sanitize.ts only, since the .replace chain is exactly the kind of code mutation testing catches.

Decision requested: A accept the conformance-test gate (hive implements), B accept but only the 8-bit ST fix now and defer the gate, C decline — keep fixing per-site.

Risk: governance

Prior instances: #414, #416. Fixing PRs: #415, #417.

— hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88

Activity

  1. added
    agent/scannerCreated by Hive for agent-filed issue provenance
    stage/045-needs-decisionIssue parked on a person: needs-human or a maintainer decision is owed before the hive picks it up
    on Oct 29, 2026
  2. added
    help wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.
    on Oct 29, 2026
  3. hivecommons-hive commented on Oct 29, 2026

    @hivecommons-hive
    ContributorAuthor

    What to reply

    • /hive approve: go with the recommendation
    • /hive decision <your instructions>: go ahead, following your instructions
    • /hive help: show these again

    If what this issue waited on has been done (a merged fix, or an action taken outside this repository), a maintainer can reply /fixed to close it as completed; Hive clears its park labels.

    Only a maintainer with write access can un-park; everything else is ignored. Full command reference: https://github.com/hivecommons/hive/blob/v5/src/docs/maintainer-commands.md.

  4. added
    stage/010-actionableTriaged; eligible for the hive to pick up
    and removed
    stage/045-needs-decisionIssue parked on a person: needs-human or a maintainer decision is owed before the hive picks it up
    on Oct 29, 2026
  5. hivecommons-hive commented on Oct 29, 2026

    @hivecommons-hive
    ContributorAuthor

    Un-parked by @clubanderson. Decision: go with the recommendation

    stage/045-needs-decision is cleared when present and approved-direction is applied; any hold label is left exactly as it was.

    Recorded from the hive dashboard.

  6. hivecommons-hive commented on Oct 29, 2026

    @hivecommons-hive
    ContributorAuthor

    🔒 Claimed by @Karibhou (contributor on hive hosted-available-oke-11-placeholder-r05x). The claim lasts 30m0s without activity and renews while the work continues. Reply /unclaim to release, or /claim to take it over if you outrank the holder.

  7. hivecommons-hive commented on Oct 29, 2026

    @hivecommons-hive
    ContributorAuthor

    🔓 Claim by @Karibhou released (lease revoked).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/scannerCreated by Hive for agent-filed issue provenanceapproved-directionhelp wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions