Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-2436Done

BUG — the sandbox smoke's stub server still speaks MCP only, so every image smoke test 405s the moment the CLI moved to `/api/v1`

packages/cli/sandbox/smoke/stub-server.mjs is the zero-dependency server the sandbox IMAGE smoke tests run the built motir binary against. It speaks MCP JSON-RPC and nothing else — a TOOLS table dispatching whoami / list_ready / next_ready / transition_status / dispatch_prompt / mark_integrated over POST, plus the two /api/cli/device/* routes.

Since MOTIR-2214 (11.5.6) the CLI makes no MCP calls at all. Every read is now a GET /api/v1/..., and this server's first branch is:

if (req.method === 'GET') {
  res.writeHead(405, ...).end('{"error":"no sse stream"}');
  return;
}

So the very first request of every smoke run gets a 405. Nothing after it can pass.

⚠️ THIS TURNS THE PARENT PR RED

ci.yml's sandbox job calls sandbox-images.yml on every pull request, skipping only seed/ · design/ · docs/ branches. The story's branch is none of those, so the image lane runs and fails. This is a merge blocker for Story 11.5, not a deferred cleanup.

What to build

  1. Serve /api/v1 from the stub. Route by method + path pattern (the routes the smoke loop actually drives): GET /api/v1/me, GET /api/v1/workspaces, GET /api/v1/projects, GET /api/v1/projects/{key}/ready, GET /api/v1/work-items/{key}, GET /api/v1/work-items/{key}/dispatch-prompt, POST /api/v1/work-items/{key}/transitions, POST /api/v1/work-items/{key}/integration, POST /api/v1/sessions/complete. Drive the exact set from what the smoke scripts exercise rather than from this list — the list is a starting point, not a contract.
  2. Keep the recording. assert-run.mjs asserts the recorded call SEQUENCE, which is the thing an exit code cannot tell you. The recorded shape becomes METHOD path rather than a tool name; update the assertions with it, and keep the sequence check — it is what proves the loop's ORDER, not merely its outcome.
  3. Keep it zero-dependency. It runs under the bare node in the image; no imports beyond node:*.
  4. Decide the fate of the MCP half. The device routes stay (login is unchanged). The TOOLS table has no caller once (1) lands — delete it rather than leave a second protocol nothing drives, on the same principle 11.5.6 applied to the client.
  5. The response bodies must be REAL v1 shapes. The CLI validates every response against its generated Ajv validator, so a hand-approximated body is rejected by the client before any renderer sees it — this stub cannot fake loosely the way the MCP one could.

Scope BOUNDARY

Ends at the stub server, the smoke scripts' assertions, and sandbox/README.md's description of them. It does NOT change the CLI, the image, the Dockerfile, the profile matrix or the device-grant flow. It does NOT touch the CodeGraph MCP wiring in the same README — that is the AGENT's MCP server for code search and is entirely unrelated to the CLI's transport.

Acceptance criteria

  • packages/cli/sandbox/smoke/run.sh passes end to end against the built image, with the CLI making only /api/v1 and /api/cli/device/* requests.
  • assert-run.mjs still asserts an ORDERED sequence, now over v1 requests, and is proven to fail when the order is wrong.
  • Every scripted response body validates against the generated client's Ajv validator for its operation — asserted, not assumed, since the client rejects a body that does not.
  • No tools/call / tools/list handling remains in stub-server.mjs.
  • packages/cli/sandbox/README.md's smoke section describes what the stub now serves; its CodeGraph MCP sections are untouched.
  • The Sandbox images job is green on the story's pull request.

Context refs

  • packages/cli/sandbox/smoke/stub-server.mjs — the file; note the GET → 405 branch at the top of the request handler is the immediate failure.
  • packages/cli/sandbox/smoke/{loop,failure,login,readonly-login}-smoke.sh — the four scripts that start it, and the source of the operation set to serve.
  • packages/cli/sandbox/smoke/assert-run.mjs — the sequence assertions to re-point.
  • tests/helpers/mcpHttpServer.ts — a path-pattern matcher with literal-beats-dynamic precedence already exists there; the shape is worth copying, but this file cannot import it (zero-dependency, runs in the image).
  • .github/workflows/ci.yml § sandbox — why this is a PR blocker rather than a nightly one.
  • Caused by: MOTIR-2214 · Found by: MOTIR-2217.
  • Story: MOTIR-1855.