Skip to content

[Stage 3 / P2] refactor: split slash.js into interaction/ + feedback/ subsystems #27

Description

@modacker

[Stage 3 / P2] refactor: split slash.js into interaction/ + feedback/ subsystems

Author: @modacker
Source borrow: docs/BORROW-dsh-deepseek-harness-2026-08-28.md
borrow #3.
Related: Stage 1 event log + authorize helper should be in
place first (this refactor wires into them).

Why

server/lib/slash.js is a 304-line god module that mixes
governance and non-governance concerns. The deepseek-harness (dsh)
project demonstrates a clean split: packages/interaction/ owns
the act of asking (commands, permissions, ask-user, approvals,
questions) and packages/feedback/ owns the response on past acts
(command feedback, message feedback).

Today mcode-webui has no feedback/ concept at all — users have
no way to rate a response, no way to flag a bad tool call, no way
to say "this plan was wrong". As governance actions are added
(Stage 1 authorize + anomaly), feedback becomes load-bearing for
the "what just happened" UX.

The win is decoupling the LLM-facing API from the UI: today
mcode-webui has the LLM directly write to its chat stream. After
this refactor:

  • Slash commands can be UI-gated (per Stage 1 authorize)
  • Tool-ask-user becomes a typed modal (vs the current ad-hoc parsing)
  • Feedback events get their own append-only log entries (per Stage
    1 event log)
  • The 304-line file becomes 5–6 files of ~50–100 lines each,
    with one responsibility each

What

Mechanical refactor: split slash.js (304 lines) into:

  • server/lib/interaction/commands.js — slash command dispatch
  • server/lib/interaction/permission-presets.js — named permission
    policies (currently inline in routes/model.js#handleSetPermissions)
  • server/lib/interaction/tool-ask-user.js — mid-tool AskUser
    modal handler
  • server/lib/interaction/user-questions.js — typed question UI
    (text/choice/confirm), currently ad-hoc in routes/model.js
  • server/lib/feedback/command-feedback.js — emit feedback events
    on slash command completion
  • server/lib/feedback/message-feedback.js — emit per-message
    feedback (thumbs up/down + comment)

Each file is the seam; the SSE channel for human prompts is
the single shared transport (already exists at /api/events).

Do NOT vendor dsh's Cordis framework or its monorepo structure —
mcode-webui's design constraint is "zero npm deps". Borrow the
concept (subsystem split), not the implementation (Cordis
plugins).

Acceptance criteria

  • server/lib/slash.js no longer exists; its exports are
    re-exported from server/lib/interaction/commands.js for
    backward compatibility (or callers are updated)
  • Each of the 6 new files is ≤ 150 lines
  • No behavior change for existing tests (target 470/0/2 +
    any new tests in the new files)
  • New feedback/ modules emit events.ndjson lines (uses
    the Stage 1 event log)
  • npm test passes; npm run lint reports 0 warnings

Out of scope

  • Multi-package monorepo split — single plugin stays single plugin
  • Cordis framework adoption — would violate zero-dep contract
  • dsh's sandbox / code-runtime — mcode concern, not webui
  • mcode-side goal/ / plan/ packages — mcode concern, not webui

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions