Skip to content

PRD: Add Live IDE bridge resave-model CLI #9

@sergej-koscejev

Description

@sergej-koscejev

Problem Statement

mops helps agents inspect and edit JetBrains MPS persisted model data locally, but some useful repairs require a Live MPS instance. In particular, after an agent edits MPS model XML, the best way to refresh resolve information and let MPS normalize persistence is to ask the IDE that already has the project open to resave the loaded model.

The user needs a Live IDE bridge command family that makes this dependency explicit. The first operation is Model resave: mops sends one Model resave target to a Live MPS instance through the IDE's existing localhost HTTP server and reports whether the IDE completed the save operation.

Solution

Add a mops ide command family for IDE-backed operations. The first command is mops ide resave-model <model>.

The CLI accepts exactly one model path argument. The argument may be relative or absolute, but the CLI sends an absolute modelPath to the IDE. The model target is a path to a standalone *.mps persisted model or to a File-per-root model folder. Direct .model metadata files, direct *.mpsr root files, module-wide resaves, and project-wide resaves are outside this first slice.

The CLI talks to exactly one selected localhost port per invocation. It defaults to port 63320, allows overriding only the port on the mops ide command group, and does not accept full URL overrides, host overrides, port scanning, fallback ports, authentication, or protocol version negotiation in the first slice.

The IDE route contract is documented separately. The CLI consumes the route's success and structured error responses and turns local connection/protocol failures into stable CLI error codes.

User Stories

  1. As an agent editing MPS model XML, I want to ask the open IDE to resave one model, so that MPS can update resolve information and normalize persistence.
  2. As an agent, I want the command to live under mops ide, so that I can tell it depends on a Live MPS instance.
  3. As a user, I want mops ide resave-model to target one model at a time, so that output and failure handling stay simple.
  4. As a user, I want to pass a normal filesystem path, so that I can target the persisted model I just edited.
  5. As a user, I want relative paths to work, so that I can call the command naturally from my working tree.
  6. As an IDE route implementer, I want the CLI to send an absolute modelPath, so that route behavior does not depend on the CLI working directory.
  7. As an agent, I want the command to accept standalone *.mps model paths, so that default XML persistence models can be resaved directly.
  8. As an agent, I want the command to accept File-per-root model folders, so that file-per-root models can be resaved as complete models.
  9. As an agent, I do not want to pass direct .model metadata files, so that the command does not imply metadata-only save behavior.
  10. As an agent, I do not want to pass direct *.mpsr root files, so that the command does not imply root-only model resave behavior.
  11. As a user, I want the CLI to avoid local model-shape preflight, so that the Live MPS instance remains the authority for loaded project state.
  12. As a user, I want the CLI to report IDE target failures using the IDE's stable error code and message, so that I can distinguish missing models from save failures.
  13. As a user, I want a clear error when no IDE responds on the selected port, so that I know the Live MPS instance is not reachable.
  14. As a user, I want a clear protocol error when something responds but not with the mops route contract, so that I know to check whether the mops IDE plugin is installed.
  15. As a user, I want only the port to be configurable, so that I can target a non-default IDE server without creating arbitrary URL behavior.
  16. As a user, I want port configuration to belong to the mops ide command group, so that future IDE-backed operations share the same connection semantics.
  17. As a user, I want the bridge to contact exactly one selected port, so that it does not accidentally talk to the wrong MPS-based IDE.
  18. As an automation runner, I want a finite timeout, so that a stuck IDE request does not hang indefinitely.
  19. As an automation runner, I want a successful save to exit 0, so that scripts can treat it as completed work.
  20. As an automation runner, I want IDE-reported failures to exit non-zero, so that scripts stop when the model was not resaved.
  21. As an agent, I want terse human output on success, so that command output is easy to read and chain in logs.
  22. As an agent, I want stable error codes on failure, so that I can branch on IDE_UNREACHABLE, IDE_PROTOCOL_ERROR, and IDE-provided model/save errors.
  23. As a maintainer, I want Model resave to stay separate from Model validation, so that resave does not silently add a second operation with different failure modes.
  24. As a maintainer, I want no dry-run behavior on resave-model, so that the mutating route remains honest and any future non-mutating probe can be a separate endpoint.
  25. As a maintainer, I want no bridge protocol version in the first slice, so that compatibility policy is not invented before there is version pressure.
  26. As a maintainer, I want no open-project verification from the CLI, so that project-state authority remains in the Live MPS instance.
  27. As a future bridge implementer, I want the mops ide namespace to be a general Live IDE bridge, so that later IDE-backed operations have an obvious home.
  28. As a reviewer, I want the CLI feature to be implemented after the repository reshape, so that it lands in the settled cli subproject layout.
  29. As a reviewer, I want the IDE route behavior to remain separately specified, so that the CLI PR can be reviewed against a stable route contract without owning MPS implementation details.
  30. As a user, I want the command to avoid module-wide and project-wide resaves for now, so that the first operation does one clear thing.

Implementation Decisions

  • Add a mops ide command family for Live IDE bridge functionality.
  • Add resave-model as the first IDE-backed operation under that command family.
  • The first command accepts exactly one Model resave target.
  • The Model resave target is a filesystem path, not a raw MPS model reference string.
  • The CLI accepts relative or absolute input paths and sends an absolute modelPath to the IDE.
  • The CLI does not check target existence or persisted-model shape before calling the IDE.
  • The Live MPS instance resolves modelPath against its currently open project.
  • The CLI does not verify that the IDE's open project matches the CLI working tree.
  • The CLI defaults to port 63320.
  • Only the port is configurable; the CLI does not accept full URL, host, or scheme overrides.
  • The port option belongs to the mops ide command group rather than to resave-model.
  • The CLI contacts exactly one selected port per invocation and does not scan or fall back across ports.
  • The first slice relies on localhost-only access and does not add authentication or a shared secret.
  • The first slice does not include protocol version negotiation.
  • The first slice does not add a JSON output mode for resave-model.
  • On success, the CLI prints saved <absolute-model-path> to stdout and exits 0.
  • On IDE-reported failure, the CLI prints <CODE>: <message> to stderr and exits non-zero.
  • If no IDE endpoint responds on the selected port, the CLI reports IDE_UNREACHABLE.
  • If something responds but does not follow the mops IDE route contract, the CLI reports IDE_PROTOCOL_ERROR and suggests checking that the mops IDE plugin is installed.
  • The CLI uses a 30-second request timeout and does not expose timeout configuration in the first slice.
  • A request timeout is reported as IDE_UNREACHABLE.
  • Model resave does not automatically run Model validation.
  • resave-model has no dry-run behavior; a future non-mutating probe/status operation should use a separate endpoint.
  • Module-wide and project-wide resave operations are future separate operations, not flags or batch behavior in the first command.
  • Implement this after the repository reshape PRD, so the command lands in the cli subproject.
  • Treat the existing IDE route specification as the route contract for this CLI work.

Testing Decisions

  • Tests should assert CLI behavior at the command boundary rather than internal HTTP-client implementation details.
  • Existing command tests are prior art for command parsing, stdout/stderr behavior, and exit codes.
  • Add tests with a fake HTTP server for successful IDE responses.
  • Add tests proving relative CLI paths are sent as absolute modelPath values.
  • Add tests proving the default port is 63320.
  • Add tests proving the mops ide port option changes the selected port.
  • Add tests proving full URL overrides are not accepted.
  • Add tests proving exactly one model target is required.
  • Add tests proving multiple model targets are rejected.
  • Add tests proving successful saved: true responses print saved <absolute-model-path> and exit 0.
  • Add tests proving structured IDE error responses print the stable code plus message and exit non-zero.
  • Add tests proving connection failures report IDE_UNREACHABLE.
  • Add tests proving request timeouts report IDE_UNREACHABLE.
  • Add tests proving malformed JSON, non-JSON, or unexpected response shapes report IDE_PROTOCOL_ERROR and include the plugin-installed hint.
  • Add tests proving the CLI does not locally reject missing model paths before attempting the IDE request.
  • Add tests proving the CLI does not run Model validation after a successful resave.
  • Do not test IDE route internals in this PRD; those belong to the IDE route implementation and its separate route contract.

Out of Scope

  • Repository reshaping into the Gradle-rooted cli/ide monorepo.
  • Implementing the MPS-side IDE route.
  • Implementing the MPS plugin artifact.
  • Testing MPS route internals.
  • Running Model validation automatically after resave.
  • Resaving multiple models in one invocation.
  • Module-wide resave.
  • Project-wide resave.
  • Dry-run, probe, or status endpoints.
  • Full URL, host, or scheme overrides.
  • Port scanning or fallback port discovery.
  • Authentication or shared-secret setup.
  • Bridge protocol version negotiation.
  • Verifying the IDE open project against the CLI working tree.
  • JSON output mode for resave-model.

Further Notes

  • This PRD assumes the repository reshape PRD lands first.
  • This PRD uses the domain terms Live IDE bridge, Live MPS instance, IDE-backed operation, Model resave, Model resave target, Persisted model, File-per-root model folder, and Model validation.
  • The IDE route contract for Model resave is documented separately and intentionally contains only the IDE-side route behavior and route test plan.
  • The first command is intentionally narrow: one target, one port, one mutating operation.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions