[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
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
[Stage 3 / P2] refactor: split slash.js into
interaction/+feedback/subsystemsWhy
server/lib/slash.jsis a 304-line god module that mixesgovernance and non-governance concerns. The deepseek-harness (dsh)
project demonstrates a clean split:
packages/interaction/ownsthe 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 haveno 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:
1 event log)
with one responsibility each
What
Mechanical refactor: split
slash.js(304 lines) into:server/lib/interaction/commands.js— slash command dispatchserver/lib/interaction/permission-presets.js— named permissionpolicies (currently inline in
routes/model.js#handleSetPermissions)server/lib/interaction/tool-ask-user.js— mid-toolAskUsermodal handler
server/lib/interaction/user-questions.js— typed question UI(text/choice/confirm), currently ad-hoc in
routes/model.jsserver/lib/feedback/command-feedback.js— emit feedback eventson slash command completion
server/lib/feedback/message-feedback.js— emit per-messagefeedback (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.jsno longer exists; its exports arere-exported from
server/lib/interaction/commands.jsforbackward compatibility (or callers are updated)
any new tests in the new files)
feedback/modules emitevents.ndjsonlines (usesthe Stage 1 event log)
npm testpasses;npm run lintreports 0 warningsOut of scope
sandbox/code-runtime— mcode concern, not webuigoal//plan/packages — mcode concern, not webui