Skip to content

screen.edit() (and underlying edit_screens) returns success but never persists the change #361

Description

@RiddikZ

Summary

screen.edit() — and the edit_screens tool it wraps — accepts the request and returns a confident success (an agent message like "I've updated the heading to …" plus a precise dom_operations replace_content), but no new screen version is created and the change never renders. getHtml() after the edit returns the unchanged HTML. The same single-change edit applied in the Stitch web UI on the same screen works — so the bug is in the edit_screens write path, not in reads or in Stitch's edit capability.

Environment

  • @google/stitch-sdk (latest), Node + TS. Auth via STITCH_API_KEY.
  • Also reproduced via the raw Stitch MCP (stitch.googleapis.com/mcp, X-Goog-Api-Key) calling edit_screens directly.
  • All other operations work fine: generate, getHtml, getImage, list, create_project, design-system tools.

Repro (SDK)

import { stitch } from "@google/stitch-sdk"; // STITCH_API_KEY in env

const { result } = await stitch.callTool("create_project", { title: "edit-bug-repro" });
const projectId = result /* projects/<id> */ .split("/").pop();
const project = stitch.project(projectId);

const screen = await project.generate(
  'A minimal screen with one large centered heading that reads exactly "ORIGINAL HEADING ALPHA".',
);
const before = await fetch(await screen.getHtml()).then((r) => r.text());
// before contains "ORIGINAL HEADING ALPHA"  ✅

const edited = await screen.edit(
  'Change the heading text to read exactly "EDITWORKS BRAVO 9X". Change nothing else.',
);
// edited resolves OK; the agent reports success + dom_operations replace_content → "EDITWORKS BRAVO 9X"

const after = await fetch(await edited.getHtml()).then((r) => r.text());
// EXPECTED: after contains "EDITWORKS BRAVO 9X"
// ACTUAL:   after === before  → still "ORIGINAL HEADING ALPHA", byte-identical, same file id

Expected: after edit(), the screen's HTML reflects the requested change (a new version).

Actual: HTML is byte-identical to the pre-edit version; the screen's file id is unchanged even after a project refresh and several minutes. The change is silently not applied, despite the success response.

Discriminator (key)

Applying the identical edit through the Stitch web UI on the same screen — both a whole-screen prompt and an element-scoped prompt — does persist: a subsequent getHtml() immediately returns a new file id with the change. So reads are correct; only the programmatic edit_screens write path fails to persist.

Additional notes

  • Reproduced on existing, duplicated, and brand-new projects — identical result (not project-age related).
  • One edit_screens call once returned 401 "Expected OAuth 2 access token, login cookie or other valid authentication credential", though other calls (and every other tool) authenticate fine with the API key.

Impact

Any programmatic edit is a no-op. This also breaks the Edit flow of the official stitch-design/generate-design skill, which calls edit_screens.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions