Files
msd-core/docs/adr/1787-msd-next-smart-entry.md
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
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.
2026-10-06 01:47:40 +02:00

124 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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-next` command (#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:
1. **A `msd-next` command already existed and was deliberately removed (#3054),**
with `/msd:progress --next` established as the canonical "advance to the next
logical step" engine. `tests/bug-3054-stale-msd-next-references.test.cjs`
guards against user-facing surfaces re-referencing the removed flat command.
Re-introducing a `next` entry point re-opens a settled question: it must not
recreate the duplication that justified the removal.
2. **`/msd:progress` is the "unified MSD situational command."** Its `--next`
mode (`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`'s `current_phase` advanced past a phase
that still has `PLAN.md` files without matching `SUMMARY.md`, `--next`
resumes 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.
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:
1. **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`),
using `AskUserQuestion` with a `--text` numbered-list fallback for non-Claude
runtimes. The command carries no `requires` field so it works pre-project.
2. **In-project forward motion delegates to the single gated engine.** For the
`planning`, `executing`, and `verify-pending` situations, the *recommended*
action is `/msd:progress --next`. smart-entry never re-derives forward routing;
it hands linear advancement to `workflows/next.md` so 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.
3. **smart-entry's distinct value is the states `--next` cannot reach.** For
situations *off* the linear advance path it keeps direct recommendations, since
these are precisely what `/msd:progress --next` does not (or cannot, given its
`requires: [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:next` and `/msd:progress --next` can 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 `--next` structurally cannot serve.
- **Testable boundary.** `tests/smart-entry.unit.test.cjs` asserts that every
forward-motion situation recommends `/msd:progress --next` and 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 through `workflows/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
1. **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.
2. **Fold everything into `/msd:progress` (add a menu mode) and ship no new
command.** Rejected: `/msd:progress` carries `requires: [phase]` and cannot
serve the pre-project `no-project` front-door case, which is a primary goal.
3. **Replace `workflows/next.md`'s inline detection with the new classifier so
there is one detection *and* routing engine.** Rejected for this PR: `--next`
couples 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