Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
6.9 KiB
ADR 1787: /msd:next smart-entry front door delegates advancement to /msd:progress --next
- Status: Accepted
- Date: 2026-07-03
- Issue: #1787
- Implementation: PR #1798 (
feat(#1787): add /msd:next smart entry workflow) - Supersedes context: the removal of the flat
msd-nextcommand (#3054)
Context
msd-core has no state-aware front door. A user must already know whether to
reach for /msd:progress, /msd:plan-phase, /msd:execute-phase, /msd:quick,
or /msd:new-project. gsd-pi ships a /msd smart-entry wizard (a state-aware
menu with one recommended action) that users run first; msd-core wants the same
"run one command, get told what to do next" feel without gsd-pi's TUI, since
msd-core is a markdown prompt framework installed into AI agents, not a Node app.
Two facts constrain the design:
-
A
msd-nextcommand already existed and was deliberately removed (#3054), with/msd:progress --nextestablished as the canonical "advance to the next logical step" engine.tests/bug-3054-stale-msd-next-references.test.cjsguards against user-facing surfaces re-referencing the removed flat command. Re-introducing anextentry point re-opens a settled question: it must not recreate the duplication that justified the removal. -
/msd:progressis the "unified MSD situational command." Its--nextmode (msd-core/workflows/next.md) is a gated advancement engine:- Route 0 — the resume-incomplete-phase invariant (#160): if a session
died mid-execution and
STATE.md'scurrent_phaseadvanced past a phase that still hasPLAN.mdfiles without matchingSUMMARY.md,--nextresumes the incomplete earlier phase rather than the recorded current one. - Gates 1–3 — unresolved checkpoint, error/failed state, and unchecked verification failures each hard-stop advancement.
- Route 0 — the resume-incomplete-phase invariant (#160): if a session
died mid-execution and
The initial implementation of the new smart-entry classifier
(src/smart-entry.cts) re-derived in-project forward routing itself. For the
executing situation it recommended dispatching /msd:execute-phase directly,
bypassing Route 0 and Gates 1–3. That reproduced exactly the duplication that got
msd-next removed — two front doors that can route the same in-project state
to different phases — and introduced a correctness hazard (executing the
recorded current phase while an earlier phase is silently incomplete). A
maintainer (davesienkowski) flagged the overlap on PR #1798.
Decision
Ship /msd:next as a menu front door only, with a hard boundary against
re-implementing advancement:
-
Detection + classification live in Node as
msd-tools smart-entry [--json](src/smart-entry.cts): a pure, unit-tested classifier over.planning/STATE.md,ROADMAP.md, and read-only git signals, producing one of 11 situations with a recommended action and an action menu. Presentation + dispatch live in the markdown layer (commands/msd/next.md→msd-core/workflows/smart-entry.md), usingAskUserQuestionwith a--textnumbered-list fallback for non-Claude runtimes. The command carries norequiresfield so it works pre-project. -
In-project forward motion delegates to the single gated engine. For the
planning,executing, andverify-pendingsituations, the recommended action is/msd:progress --next. smart-entry never re-derives forward routing; it hands linear advancement toworkflows/next.mdso Route 0 and Gates 1–3 are always honored. The specific command (/msd:plan-phase,/msd:execute-phase,/msd:verify-work) remains available as an explicit secondary menu option for a user who deliberately wants to bypass advancement gating. -
smart-entry's distinct value is the states
--nextcannot reach. For situations off the linear advance path it keeps direct recommendations, since these are precisely what/msd:progress --nextdoes not (or cannot, given itsrequires: [phase]) handle:no-project→/msd:new-project,paused→/msd:resume-work,blocked→/msd:debug,verify-failed→/msd:verify-work,needs-first-phase→/msd:discuss-phase,idle-stranded→/msd:ship,complete→/msd:new-milestone,unknown→/msd:progress.
This makes the spec's stated decision #4 ("complementary, not redundant") true in
the implementation, not just the prose: there is exactly one advancement engine,
and /msd:next is a menu over it plus the off-path states.
Consequences
Positive
- One advancement engine.
/msd:nextand/msd:progress --nextcan never disagree about the next in-project step, and Route 0 / Gates 1–3 cannot be bypassed through the new front door. The #3054 duplication does not return. - Genuine new value, no overlap. The front door adds pre-project, remediation,
and lifecycle-exit routing that
--nextstructurally cannot serve. - Testable boundary.
tests/smart-entry.unit.test.cjsasserts that every forward-motion situation recommends/msd:progress --nextand every off-path situation keeps its direct recommendation — the delegation is a regression-locked contract, not a convention.
Negative / trade-offs
- One extra indirection hop for the common "just continue" case (
/msd:next→/msd:progress --next→ dispatched command) versus dispatching the phase command directly. Accepted: the hop is what buys gate-safety and single-engine behavior. - The classifier reads STATE.md via shared primitives (
frontmatter.cjs,state-document.cjs,phase-id.cjs) rather than throughworkflows/next.md's own detection, so detection logic exists in two places. Accepted: they share parsing primitives and only the routing decision is centralized (in--next), which is where divergence would actually harm the user.
Alternatives considered
- Keep smart-entry as an independent in-project router (as first implemented). Rejected: reproduces the #3054 duplication and the Route 0 / Gates 1–3 bypass hazard.
- Fold everything into
/msd:progress(add a menu mode) and ship no new command. Rejected:/msd:progresscarriesrequires: [phase]and cannot serve the pre-projectno-projectfront-door case, which is a primary goal. - Replace
workflows/next.md's inline detection with the new classifier so there is one detection and routing engine. Rejected for this PR:--nextcouples detection to safety gates and convergence flags the classifier does not model; swapping its detection wholesale would risk regressing those invariants. Left as possible future consolidation.
References
- Spec:
docs/superpowers/specs/2026-06-27-msd-smart-entry-design.md - Removed flat command guard:
tests/bug-3054-stale-msd-next-references.test.cjs - Gated engine:
msd-core/workflows/next.md(Route 0 = resume-incomplete-phase, #160) - Classifier:
src/smart-entry.cts→msd-core/bin/lib/smart-entry.cjs - Command contract naming (
msd:*): ADR-0002